This replaces (now deprecated but still functional) options
`--mathml`, `--mathjax`, `--gladtex`, `--katex`, `--webtex`.
The `plain` style can now be specified explicitly.
In defaults files, `html-math-method` is now
`math-method` (though `html-math-method` will still work).
Text.Pandoc.App.Opt:
- In unexported type CompletionKind, add MathMethods.
- In Opt, change `optHTMLMathMethod` to `optMathMethod`. [API change]
Text.Pandoc.Options:
- Rename HTMLMathMethod type to MathMethod. [API change]
- Rename `writerHTMLMathMethod` field of WriterOptions to
`writerMathMethod`. [API change]
Text.Pandoc.App.Completion:
- Clean up code.
- Add support for `--math-method`.
Given RST like
.. _target:
See |sub|.
.. |sub| replace:: `text <target_>`_
'pandoc -f rst -t html' produces
<div id="target">
<p>See <a href="##REF##target">text</a>.</p>
</div>
instead of the expected
<div id="target">
<p>See <a href="#target">text</a>.</p>
</div>
It formerly worked and regressed with c8fda8f4d ("RST reader: Use a new
one-pass parsing strategy."), release 3.6.
What happens is that during parsing pass 1 the `replace::` value `text
<target_>`_ is parsed to
Link nullAttr [Str "text"] ("##REF##target", "")
and is stored in ParserState's substitution table. Separately, '|sub|'
usage is parsed to
Link nullAttr [Str "|sub|"] ("##SUBST##|sub|", "")
and is stored in the document tree. resolveReferences then replaces the
placeholder in the document node with substitution table node during
walkM. However, the freshly substituted ##REF## placeholder was not
revisited further, and appeared unresolved in the output.
To fix it, we resolve the node recursively until the result contains no
more placeholder. We must protect from self-references to avoid
endless recursion.
Previously, when a slide contained bullet points before and after a
table, content would be split across multiple slides or use a two-column
layout that didn't preserve the source order.
This change:
1. Modified `splitBlocks'` in Presentation.hs to continue accumulating
content after tables instead of immediately splitting to a new slide.
2. When a slide has a table with surrounding text, use ContentSlide
(single column) instead of ContentWithCaptionSlide (two columns)
to preserve content order.
3. Added vertical stacking in Output.hs (shapesToElementsStacked) to
properly position multiple shapes (tables + text) within a content
area. Space is allocated proportionally based on content size
(paragraphs and table rows).
Closes#11433.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Chris Callison-Burch <ccb+github@upenn.edu>
`t2t` is now supported as an output format, producing Txt2Tags
markup (<https://txt2tags.org>). The writer covers headers, lists
(bullet, ordered, definition), tables, links, images, code blocks,
inline formatting, and raw txt2tags/HTML passthrough.
[API change]
Adds a new module Text.Pandoc.Writers.Txt2Tags, exporting
`writeTxt2Tags`. Also exported from Text.Pandoc.Writers.
Co-authored-by: luginf <alan@luginf>
When a reference document uses a non-standard namespace prefix for the
WordprocessingML namespace (e.g. `ns0` instead of `w`), `sectPr` elements
copied from the reference would retain the non-`w` prefix, producing
malformed XML in the output document. Similarly,
`extractPageLayout` only matched elements with prefix `w`, missing
`sectPr` elements with other prefixes. This is fixed by matching on the
namespace URI rather than the prefix, and normalizing the prefix to `w`
on all elements and attributes copied from reference-doc `sectPr`.
Some new tests have been added, and the test suite has been streamlined
using helper functions.
Word represents "restart numbering" on a style-based list by pointing
only the first item of the restarted list at a new `numId` that shares the
original list's abstract numbering definition but carries a
`w:startOverride`; the remaining items keep using the original `numId`.
Pandoc keyed list continuation and grouping on the `numId`, so the
restarted items continued the stale count from the earlier list (and
were split into a separate ordered list with the wrong start).
Key continuation and grouping off the `abstractNumId` instead (the real
running counter in Word), and treat `startOverride` as a restart that
resets the count.
Closes#8367.
Co-Authored-By: Claude <noreply@anthropic.com>
Word-95-style numbered and bulleted lists are encoded with a
`{\pntext ...}` auto-number destination at the start of each list
paragraph plus a `{\*\pn ...}` destination describing the numbering,
rather than the modern `\listtext`/`\listtable` mechanism. Two problems:
1. The `\pntext` marker text ("1.", "·", etc.) was captured as the
paragraph's first text run, which sits before the paragraph's
`\ls`/`\ilvl`, so emitBlocks (which reads list properties from the first
run) misclassified the paragraph as an ordinary paragraph. The first
item of each list therefore came out as a stray paragraph.
2. The numbering style was ignored, so numbered lists defaulted to
bullets.
Treat `\pntext` like `\listtext`: drop its visible marker text and flag the
start of a new list item. Parse the `{\*\pn ...}` destination
(`\pnlvlbody`/`\pnlvlblt`, `\pndec`, `\pnucltr`, `\pnlcltr`,
`\pnucrm`, `\pnlcrm`, `\pnstart`, and the `\ls`/`\ilvl` keys it
carries) into the list override table so numbered lists are
emitted as ordered lists with the right number style.
`\pn` is a paragraph property that remains in effect until reset
by `\pard`, auto-numbering every paragraph in scope. Track
this (`sPnActive`) so each paragraph becomes its own list item,
rather than merging markerless continuation paragraphs as is done
for modern `\listtext` lists.
Co-Authored-By: Claude <noreply@anthropic.com>
The reader treated every list paragraph as a new list item, so a list
item containing several paragraphs was split into one item per
paragraph. In the RTF list model a new item is marked by a
`{\listtext ...}` destination group; a list paragraph lacking one is a
continuation of the current item.
Track whether a `{\listtext}` group was seen (`sListText`) and, in
`emitBlocks`, append a continuation paragraph (no `\listtext`) to the
current item rather than starting a new one.
Adds a `list_multiparagraph` reader test.
Co-Authored-By: Claude <noreply@anthropic.com>
When parsing an inline note (`^[...]`) inside a quoted span,
`stateQuoteContext` was still set to `InSingleQuote`/`InDoubleQuote`,
so quotes within notes failed to parse as `Quoted` nodes.
Fix this by wrapping the note body parser in
`withQuoteContext NoQuote`.
Closes#11613.
When a heading contained a footnote, processing the footnote's block
content would consume the stFirstPara flag, causing the following
paragraph to incorrectly receive BodyText style instead of
FirstParagraph. Fix by saving and restoring stFirstPara around
footnote block processing.
Closes#11573.
Co-Authored-By: Claude <noreply@anthropic.com>
MediaBag test used `inDirectory` (which calls `setCurrentDirectory`),
changing the process-wide CWD and causing other parallel tests
to fail with "does not exist" errors on relative paths.
Replace with absolute paths so the test no longer changes CWD.
Closes#11566.
Co-Authored-By: Claude <noreply@anthropic.com>
Previously, when a w:p paragraph contained runs with textboxes,
the entire paragraph was replaced by just the textbox content,
discarding all other runs (including image-bearing runs).
Now we walk the paragraph's children in order, grouping
non-textbox content into copies of the original w:p and splicing
unwrapped textbox content in place, preserving the original order.
We also treat text inside a textbox containing an image as a
figure caption. (One often finds captioned images of this
kind in docx files.)
Closes#11510.
Closes#6893.
Closes#11412.
Closes#5394.
Closes#9633.
Co-Authored-By: Claude <noreply@anthropic.com>
Previously, the fix for #10578 (removing leading section break to avoid
blank first page) was implemented inside blocksToOpenXML, which is called
recursively for Div contents. Since makeSectionsWithOffsets wraps each
section in a Div, this caused ALL section breaks to be stripped, not just
the first one (#11482).
This commit fixes the issue by tracking whether we've processed the first
section header using a new stFirstSectionHeader state flag. Section breaks
are now correctly added between chapters/parts while still avoiding a
blank first page.
Closes#11482.
See also #10578.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
pandoc generates a separate style class like P123 for each paragraph,
inheriting the desired style using `parent-style-name`.
Previously, we did not support that but it is pretty easy to add.
Though for simplicity this fix does not extend to finding the parent
style recursively when deeper hierarchies are involved.
LibreOffice uses `Preformatted_20_Text` as the default style for
code listings etc. Let’s detect if a paragraph has the `style-name`
and convert it to `CodeBlock` if it is the case.
Unfortunately, pandoc itself generates a separate style class like P123
for each paragraph so we will not yet support code listings from documents
generated by pandoc itself.
Closes#4841.
Table rows in Docx files can use `w:gridBefore` property to specify
a number of extra empty table cells to be inserted at the beginning
of a row. Without this, table columns in tables using the element
will become misaligned.
https://learn.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.gridbefore?view=openxml-3.0.1
In the worst case, this can lead to cells at the end of some rows
to be dropped by the parser.
The test file was produced as follows based on
the “3GPP TS 24.282 V19.5.0 (2025-12)” document obtained from
<https://www.3gpp.org/ftp/Specs/archive/24_series/24.282/24282-j50.zip>
where I encountered the issue:
1. Extracted the `document.xml`.
2. Formatted it with `xmllint --format`.
3. Found the raw XML for “Table 15.2.13-2: Payload content type”.
4. Removed `w:rsid*` and `w14:*` attributes, and `w:pStyle` elements.
5. Replaced the context of `test/docx/raw-blocks.native`.
6. Used pandoc to generate the docx.
Instead of using Data.Generics `everywhere` to traverse the entire XML
tree when setting language attributes, navigate directly to the known
path w:docDefaults/w:rPr/w:lang. This is more efficient and removes the
dependency on Data.Generics (mkT, everywhere).
The new `modifyAtPath` helper function takes a list of predicates that
match element names at each level of the path and modifies only the
target element.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This adds support for a `notes` field in the YAML metadata block
that will be used as speaker notes for the title slide in PowerPoint
output.
Previously, there was no way to add speaker notes to the title slide
since it is generated from metadata rather than from content blocks.
The `::: notes` syntax only works for content slides.
Example usage:
---
title: My Presentation
notes: |
Welcome everyone to this presentation.
Remember to introduce yourself.
---
Closes#5844 (for PPTX output).
Co-authored-by: Chris Callison-Burch <ccb+github@upenn.edu>
Pandoc's docx writer was previously adding an `<Override>`
for `/word/media/` in `[Content_Types].xml` when the reference doc
contains media, which violates OPC rules and causes Word
to report corruption.
An empty `sldIdLst` is now added if the reference doc is missing one so that
`modifySldIdLst` can replace it. To ensure PowerPoint doesn't say that the file
will need fixing, the `sldIdLst` has to be placed after the `sldMasterIdLst`.
I also added a test to ensure that if there are notes, they will be placed between
the `sldMasterIdLst` and `sldIdLst`. Otherwise PowerPoint wouldn't show the
slide of a note when viewing Notes Pages.
Closes#7536.
New exported module Text.Pandoc.Readers.AsciiDoc,
exporting readAsciiDoc [API change].
The bulk of parsing is handled by the asciidoc library.
Closes#1456.
Each worksheet turns into a section containing a table.
The common file `nativeDiff` has been extract from
the Docx and Pptx text files and put in Tests.Helpers.
New module `Text.Pandoc.Readers.Pptx`,
exporting `readPptx`. [API change]
Factored out some common OOXML functions from
Text.Pandoc.Readers.Docx.Util into a non-exported module
Text.Pandoc.Readers.OOXML.Shared.
`bbcode` is now supported as an output format, as well as variants
`bbcode_fluxbb` (FluxBB), `bbcode_phpbb` (phpBB), `bbcode_steam` (Hubzilla),
`bbcode_hubzilla` (Hubzilla), and `bbcode_xenforo` (xenForo).
[API change]
Adds a new module Text.Pandoc.Writers.BBCode, exporting a number of functions.
Also exports `writeBBCode`, `writeBBCodeSteam`, `writeBBCodeFluxBB`,
`writeBBCodePhpBB`, `writeBBCodeHubzilla`, `writeBBCodeXenforo` from
Text.Pandoc.Writers.
Support for vimdoc, documentation format used by vim in its help pages.
Relies heavily on definition lists and precise text alignment to generate tags.
A new command line option `--syntax-highlighting` is provided; it takes
the values `none`, `default`, `idiomatic`, a style name, or a path to a
theme file. It replaces the `--no-highlighting`, `--highlighting-style`,
and `--listings` options.
The `writerListings` and `writerHighlightStyle` fields of the
`WriterOptions` type are replaced with `writerHighlightStyle`.
Closes: #10525
If a `latex-pos` attribute is present on a figure, it will be used as the
optional positioning hint in LaTeX (e.g. `ht`).
With implicit figures, `latex-pos` will be added to the figure (and
removed from the image) if it is present on the image.
Closes#10369.
Sub- and superscript must be preceded by a string in Org mode. Some text
preceded by space or at the start of a paragraph was previously parsed
incorrectly as sub- or superscript.
Org mode makes a distinction between smart parsing of quotes, and smart
parsing of special strings like `...`. The finer grained control over
these features is necessary to truthfully reproduce Emacs Org mode
behavior. Special strings are enabled by default, while smart quotes are
disabled.
The behavior of `special_string` is brought closer to the reference
implementation in that `\-` is now treated as a soft hyphen.
Translating entities by name ultimately relies on
Commonmark.Entity.lookupEntity, which de facto requires the entity name
to be followed by a semicolon. Paste a semicolon onto the end of the
entity name read from POD to look it up.
Fixes#11015
This adds a reader and writer for an XML format equivalent to `native`
and `json`.
XML schemas for validation can be found in `tools/pandoc-xml.*`.
The format is documented in `doc/xml.md`.
API changes:
- Add module Text.Pandoc.Readers.XML, exporting `readXML`.
- Add module Text.Pandoc.Writers.XML, exporting `writeXML`.
A new unexported module Text.Pandoc.XMLFormat is also added.