163 Commits

Author SHA1 Message Date
John MacFarlane 75982322cf Docx reader: improve handling of tables with uneven rows.
Previously if a table started with a 1-column row, only 1 column
would be included, even if other rows had more  columns.

Closes #11833.
2026-08-27 14:39:26 -07:00
John MacFarlane 65e6d995f9 Docx writer: initialize envLang from lang metadata.
This ensures that setting `lang` will affect the whole document.
Previously, setting `lang` to `he` was not sufficient to make
the document RTL.

See #11301.
2026-08-22 10:26:07 -07:00
Robertas 06af643730 Docx writer: use namespace URI instead of prefix in extractPageLayout (#11697)
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.
2026-06-12 18:13:10 +02:00
John MacFarlane 1b4a5356b4 Docx reader: key list numbering off abstractNumId.
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>
2026-06-09 11:59:10 +02:00
John MacFarlane c8ee9dc545 Docx reader: preserve non-textbox content when unwrapping textboxes.
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>
2026-03-14 20:12:34 +00:00
Raymond Berger f0d05eb438 Docx reader: Recognize media inside textboxes (#11515)
Closes #11053.
2026-03-12 22:26:17 +01:00
Jan Tojnar 3b9a47d02e readers/docx: Support w:gridBefore table row property (#11464)
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.
2026-02-14 14:28:03 +01:00
John MacFarlane 52120f92a6 Docx writer: replace generic XML traversal with direct path navigation.
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>
2026-01-23 23:34:03 +01:00
Ezwal fc07b06851 Docx reader: Handle REF link instruction (#11296)
This PR aims to handle a common run field instruction (fieldInstr)
from docx format :  REF, specifically those with the "link" switch \h.

In word software, you can create REF field instruction with the
Cross-reference button. You can create cross-reference to
many things such as Equation, Table, Title...
2025-11-30 13:49:58 +01:00
John MacFarlane d6c95435bf Use latest dev citeproc. 2025-10-24 23:11:26 +02:00
John MacFarlane 350b821d7c Update to use latest dev citeproc.
Fixed golden test regeneration in Docx reader test.
2025-10-18 15:03:50 +02:00
John MacFarlane d4dd5e9ab9 Docx writer: properly handle nested comment spans.
Patch credit: @mmourino.

Closes #8189. Closes #6959.
2025-10-15 23:33:04 +02:00
John MacFarlane d820620ccd Docx reader: properly calculate table column widths.
Previously we assumed that every table took up the full text
width. Now we read the text width from the document's
sectPr.

Closes #9837.
Closes #11147.
2025-09-17 14:24:33 +02:00
n.west 96fe83ecf1 reference.docx: don't left-align table header row
See #11019. Previously, centering tables in `reference.docx` would leave
the header row left-aligned. Why the OOXML 'standard' would allow table
elements to be aligned differently from the rest of the table in the
first place is anyone's guess.
2025-08-04 15:07:58 -07:00
John MacFarlane ae68554538 Fix docx golden tests for East Asian default style changes. 2025-06-10 18:11:24 -07:00
John MacFarlane af57648e58 Docx writer: preserve Relationships for images from reference docx.
This should allow one to include an image in a reference.docx and
reference it in an openxml template.

Closes #10759.
2025-04-05 13:48:46 -07:00
John MacFarlane 45fdd1de10 Fix invalid OOXML in definition_list.docx test.
Closes #10394.
2025-03-05 21:41:30 -08:00
John MacFarlane 3caf2b1e3a Revert "Docx reader and writer: support row heads."
This reverts commit cbe67b9602.

Word sets `w:firstColumn="1"` by default for tables.  You have to find
the Table Design tab and explicitly uncheck "First Column" to make this
go away.  In most cases, I don't think writers intend to designate
the first column as a row head, so this commit is going to produce
unexpected results.  In addition, because of the table normalization
done by pandoc-type's `tableWith`, any table containing a colspanned
cell in the left-hand column will get broken if the first column is
designated a row head.  For these reasons it seems best to revert this
change, which was made in response to #9495.

Closes #10627.
2025-02-19 10:02:50 -08:00
John MacFarlane 6fbb50fc88 Docx writer: repeat reference doc's sectPr for each new section.
Previously we were only carrying over the reference doc's sectPr
at the end of the document, so it wouldn't affect the intermediate
sections that are now added if `--top-level-division` is `chapter`
or `part`. This could lead to bad results (e.g. page numbering
starting only on the last chapter).

Closes #10577.
2025-01-31 11:44:48 -08:00
John MacFarlane a14fe6f446 Update docx golden tests for reference doc changes. 2025-01-31 09:20:51 -08:00
John MacFarlane cbe67b9602 Docx reader and writer: support row heads.
Reader: When `w:tblLook` has `w:firstColumn` set (or an equivalent bit
mask), we set row heads = 1 in the AST.

Writer: set `w:firstColumn` in `w:tblLook` when there are row
heads. (Word only allows one, so this is triggered by any number
of row heads > 0.)

Closes #9495.
2025-01-10 22:50:17 -08:00
John MacFarlane b6aff21452 Docx writer: restart footnotes by section by default.
This can be overridden by a final sectPr element in the body
of the reference.docx.

It will only change things for `--top-level-division=chapter`,
since only top-level chapters are put in separate sections.
For that use it will mean that footnote numbers start over with
each chapter, which is usually what is wanted.

Closes #2773.
2024-12-22 13:18:27 -08:00
John MacFarlane d07ada43a0 Docx reader: parse index references as empty Spans.
See #10171.
2024-12-05 10:18:48 -08:00
John MacFarlane 4b38cbbf54 Fix invalid XML in test/docx/normalize.docx.
Closes #10242.
2024-09-30 14:32:19 -07:00
John MacFarlane 6c43c03398 Docx writer: fix regression with nested lists.
Closes #9994.  The bug affects e.g. ordered lists with bullet
sublists; after the sublist the top-level list reverts to bullets
instead of being properly numbered.

This regression was introduced in version 3.2.1 and was caused by
commit f5531f1.
2024-07-27 21:01:00 -07:00
John MacFarlane b07c05a1e5 OpenXML writer: be craftier in adding East Asian font hints.
In some cases we need to break up a long text run including
both western and East Asian text, so that the punctuation in
the western text doesn't become double-wide.

Closes #9817.
2024-06-22 21:37:06 -07:00
John MacFarlane 94975a4e3c Docx reader: improve handling of captions.
- Turn captioned images into Figure elements. Closes #9391.
- Improve the logic for associating elements with captions.
  Closes #9358.
- Ensure that captions that can't be associated with an
  element aren't just silently dropped. Closes #9610.
2024-06-12 22:31:33 -07:00
John MacFarlane 3952d4d1a2 Docx reader: support task lists.
This also fixes a small bug in parsing delimiters in numbered lists,
which led to the default delimiter being used wrongly in some cases.

Closes #8211.
2024-06-04 15:17:43 -07:00
John MacFarlane e71f171fe2 T.P.Writers.Shared: export toTaskListItem instead of isTaskList.
This is more useful.  Use this in OpenXML and HTML writers.
2024-06-04 11:45:04 -07:00
John MacFarlane f5531f18a5 Docx writer: better formatting for task lists.
Task lists are now properly formatted, with no bullet.

In addition, we have removed an expensive generic traverse to
remove Space elements, and replaced it with code in
`inlinesToOpenXML`.  This should give better performance; it
also reduces XML size in the metadata, which wasn't previously
affected by the de-Spacing.

TODO: parse this in the reader so that we can have task lists round-trip.

Closes #5198.
2024-06-04 10:03:26 -07:00
John MacFarlane 39c549caad Docx writer: omit jc attribute on table cells with AlignDefault.
Closes #5662.
2024-06-01 22:31:03 -07:00
John MacFarlane 1992913ba5 Docx reader: react to "left" value on jc attribute.
Also fix tests.
2024-06-01 21:02:11 -07:00
John MacFarlane 872d7bcd28 Fix metadata in docx writer.
The new OpenXML template had spaces for metadata that need
to be filled with OpenXML fragments with the proper shape.
This patch ensures that everything is the right shape.

Closes #9828.
2024-05-31 10:43:24 -06:00
John MacFarlane a6c3945000 Docx writer: add eastAsia font hints to w:r.
We do this when the text in the run contains any CJK characters.
This ensures that ambiguous code points (e.g. quotation marks)
will be represented as "wide" characters when together with CJK
characters.

Closes #9817.
2024-05-29 15:38:34 -06:00
John MacFarlane 9753f5c114 Update reference docx for docx test. 2024-05-19 19:37:30 -07:00
John MacFarlane 1b006989b3 Fix validation errors in docx golden test. 2024-05-19 19:26:06 -07:00
John MacFarlane f874997f18 Fix abstract-title in openxml template. 2024-05-19 19:20:08 -07:00
John MacFarlane db559e100c Allow OpenXML templates to be used with docx.
The `--reference-doc` option allows customization of styles in docx
output, but it does not allow one to adjust the content of the output
(e.g., changing the order in which metadata, the table of contents,
and the body of the document are displayed), or adding boilerplate
text before or after the document body.  For these changes, one can
now use `--template` with an OpenXML template.  (See the default
`openxml` template for a sample.)

This patch also allows `--include-before-body` and
`--include-after-body` to be used with `docx` output.
The included files must be OpenXML fragments suitable for
inclusion in the document body.

Closes #8338 (`--include-before-body`, `--include-after-body`).

Closes #9069 (a custom template can be used to omit the
title page).

Closes #7256.

Closes #2928.
2024-05-19 13:09:21 -07:00
John MacFarlane c26211b0c9 Cleaned up Abstract Title and Subtitle in default reference docx.
Center Subtitle, remove color.
2024-05-18 10:50:07 -07:00
mbracke a331a1c00a Docx reader: fix anchor in header after anchor (#9626)
When the last parPart before a header was a bookmark, no span with an
anchor was added for a bookmark in the header. But the function that
adds header anchors to the anchor map, needs a span with an anchor.
So this commit adds that span.
2024-04-18 09:32:48 -07:00
John MacFarlane 066d1ba7ef reference.docx: use current standard Word theme.
This includes using the sans-serif font Aptos instead of
the serif font Cambria.

See #7280.
2024-04-13 22:31:20 -07:00
John MacFarlane e0f37996b3 reference.docx: stay closer to Word's current defaults.
We use the default styles for headings and the title instead
of what pandoc was using.

See #7280.
2024-04-13 18:15:04 -07:00
John MacFarlane b6b668ee3f Use conventional styles/indents for Word bullet lists.
See #7280.
2024-04-13 11:44:09 -07:00
John MacFarlane 6c88c39c6d Docx writer: don't copy over footnotePr in settings.xml...
rom reference.docx. Closes #9522.
2024-02-28 22:34:04 -08:00
John MacFarlane 87b07c699a Docx reader: ensure that table captions are counted.
Normally these occur outside the table element itself, but they
should still be parsed as captions in this case.

Closes #9518.
2024-02-28 10:05:15 -08:00
John MacFarlane 0706c7a285 Docx writer: restore ability to center-justify table.
The fix to #5947 caused all tables to be left indented.
This was necessary to avoid extra indentation in table cells
when a table appeared in a list item.  This change makes
the changes conditional, so that they only affect tables
in list items.

Closes #9393.
2024-02-03 22:50:55 -08:00
Edwin Török 712d746320 fix(docx): sort inline elements in schema order
Fixes #9273

```
[
    {
        "Description": "The element has unexpected child element 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:b'.",
        "Path": {
            "NamespacesDefinitions": [
                "xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\""
            ],
            "Namespaces": {

            },
            "XPath": "/w:document[1]/w:body[1]/w:p[1]/w:r[7]/w:rPr[1]",
            "PartUri": "/word/document.xml"
        },
        "Id": "Sch_UnexpectedElementContentExpectingComplex",
        "ErrorType": "Schema"
    }
]
```

Signed-off-by: Edwin Török <edwin@etorok.net>
2023-12-19 15:00:23 -08:00
Edwin Török dbd1019a97 fix(docx): fix validation error on endnotePr
Copying `endnotePr` causes validation errors, because it is now
referencing something that doesn't exist in the document:
```
  {
        "FilePath": "test/docx/golden/custom_style_reference.docx",
        "ValidationErrors": "[{\"Description\":\"Element 'w:endnote' referenced by 'endnote@http://schemas.openxmlformats.org/wordprocessingml/2006/main:id' does not exist in part '/MainDocumentPart/EndnotesPart'. The reference value is '0'.\",\"Path\":{\"NamespacesDefinitions\":[\"xmlns:w=\\\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\\\"\"],\"Namespaces\":{},\"XPath\":\"/w:settings[1]/w:endnotePr[1]/w:endnote[2]\",\"PartUri\":\"/word/settings.xml\"},\"Id\":\"Sem_MissingReferenceElement\",\"ErrorType\":\"Semantic\"},{\"Description\":\"Element 'w:endnote' referenced by 'endnote@http://schemas.openxmlformats.org/wordprocessingml/2006/main:id' does not exist in part '/MainDocumentPart/EndnotesPart'. The reference value is '-1'.\",\"Path\":{\"NamespacesDefinitions\":[\"xmlns:w=\\\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\\\"\"],\"Namespaces\":{},\"XPath\":\"/w:settings[1]/w:endnotePr[1]/w:endnote[1]\",\"PartUri\":\"/word/settings.xml\"},\"Id\":\"Sem_MissingReferenceElement\",\"ErrorType\":\"Semantic\"}]"
  }
```

For now don't copy this element, it wasn't copied before, and it doesn't
seem necessary to fix the ordering problems we had with settings.

Fixes: c9bf4da74 ("Docx writer: ensure that elements in settings are ordered correctly.")

Signed-off-by: Edwin Török <edwin@etorok.net>
2023-12-18 17:15:03 -08:00
Edwin Török 1e4775f069 fix(docx): fix validation error on w:tblHeader
```
    {
        "FilePath": "test/docx/golden/tables.docx",
        "ValidationErrors": "[{\"Description\":\"The attribute 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:val' has invalid value 'true'. The Enumeration constraint failed.\",\"Path\":{\"NamespacesDefinitions\":[\"xmlns:w=\\\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\\\"\"],\"Namespaces\":{},\"XPath\":\"/w:document[1]/w:body[1]/w:tbl[1]/w:tr[1]/w:trPr[1]/w:tblHeader[1]\",\"PartUri\":\"/word/document.xml\"},\"Id\":\"Sch_AttributeValueDataTypeDetailed\",\"ErrorType\":\"Schema\"}]"
    }
```

Although this one might actually be a bug in Open-XML-SDK similar to
this, or a subtle difference between standard versions:
https://github.com/dotnet/Open-XML-SDK/issues/780

Signed-off-by: Edwin Török <edwin@etorok.net>
2023-12-18 17:15:03 -08:00
Edwin Török fe8847bdaa fix(docx): use left vs start consistently
They are equivalent, but OOXML-Validator complains:
```
  {
        "FilePath": "test/docx/golden/tables_separated_with_rawblock.docx",
        "ValidationErrors": "[{\"Description\":\"The attribute 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:val' has invalid value 'start'. The Enumeration constraint failed.\",\"Path\":{\"NamespacesDefinitions\":[\"xmlns:w=\\\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\\\"\"],\"Namespaces\":{},\"XPath\":\"/w:document[1]/w:body[1]/w:tbl[2]/w:tblPr[1]/w:jc[1]\",\"PartUri\":\"/word/document.xml\"},\"Id\":\"Sch_AttributeValueDataTypeDetailed\",\"ErrorType\":\"Schema\"},{\"Description\":\"The attribute 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:val' has invalid value 'start'. The Enumeration constraint failed.\",\"Path\":{\"NamespacesDefinitions\":[\"xmlns:w=\\\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\\\"\"],\"Namespaces\":{},\"XPath\":\"/w:document[1]/w:body[1]/w:tbl[1]/w:tblPr[1]/w:jc[1]\",\"PartUri\":\"/word/document.xml\"},\"Id\":\"Sch_AttributeValueDataTypeDetailed\",\"ErrorType\":\"Schema\"}]"
    }
```

pandoc already uses 'left' elsewhere, so be consistent, we still produce
the transitional schema, not the strict one which would have the 'start'
attribute.

Signed-off-by: Edwin Török <edwin@etorok.net>
2023-12-18 17:15:03 -08:00