packages feed

pandoc 3.2 → 3.2.1

raw patch · 175 files changed

+3888/−2565 lines, 175 filesdep ~citeprocdep ~commonmark-extensionsdep ~crypton-connectionbinary-added

Dependency ranges changed: citeproc, commonmark-extensions, crypton-connection, djot, emojis, skylighting, skylighting-core, tasty-quickcheck, time, typst

Files

AUTHORS.md view
@@ -271,6 +271,7 @@ - Michael Snoyman - Michael Stahl - Michael Thompson+- Mickaël Canouil - Mike Tzou - Mikołaj Machowski - Milan Bracke@@ -364,6 +365,7 @@ - Terence Eden - Thenaesh Elango - Thomas Hodgson+- Thomas Soeiro - Thomas Weißschuh - Tim Lin - Tim Stewart
@@ -177,7 +177,7 @@ ------------------------------------------------------------------------ Pandoc embeds a Lua interpreter (via hslua). -Copyright © 1994–2022 Lua.org, PUC-Rio.+Copyright © 1994--2023 Lua.org, PUC-Rio.  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the
MANUAL.txt view
@@ -1,7 +1,7 @@ --- title: Pandoc User's Guide author: John MacFarlane-date: May 11, 2024+date: June 24, 2024 ---  # Synopsis@@ -928,7 +928,11 @@     `\begin{document}` command in LaTeX). This can be used to include     navigation bars or banners in HTML documents. This option can be     used repeatedly to include multiple files. They will be included in-    the order specified.  Implies `--standalone`.+    the order specified.  Implies `--standalone`. Note that if the+    output format is `odt`, this file must be in OpenDocument XML format+    suitable for insertion into the body of the document, and if+    the output is `docx`, this file must be in appropriate+    OpenXML format.  `-A` *FILE*, `--include-after-body=`*FILE*|*URL* @@ -936,7 +940,11 @@     body (before the `</body>` tag in HTML, or the     `\end{document}` command in LaTeX). This option can be used     repeatedly to include multiple files. They will be included in the-    order specified.  Implies `--standalone`.+    order specified.  Implies `--standalone`. Note that if the+    output format is `odt`, this file must be in OpenDocument XML format+    suitable for insertion into the body of the document, and if+    the output is `docx`, this file must be in appropriate+    OpenXML format.  `--resource-path=`*SEARCHPATH* @@ -1001,6 +1009,13 @@     advanced features (e.g.  zoom or speaker notes) may not work     in an offline "self-contained" `reveal.js` slide show. +    For SVG images, `img` tags with `data:` URIs are used,+    unless the image has the class `inline-svg`, in which case+    an inline SVG element is inserted. This approach is+    recommended when there are many occurrences of the same+    SVG in a document, as `<use>` elements will be used to+    reduce duplication.+ `--html-q-tags[=true|false]`  :   Use `<q>` tags for quotes in HTML.  (This option only has an@@ -1150,7 +1165,7 @@     user data directory (see `--data-dir`).  If it is not     found there, sensible defaults will be used. -`--reference-doc=`*FILE*|*URL*+[`--reference-doc=`*FILE*|*URL*]{#option--reference-doc}  :   Use the specified file as a style reference in producing a     docx or ODT file.@@ -2683,7 +2698,7 @@ :   Enables inclusion of most of the [CSS] in the `styles.html`     [partial](#partials) (have a look with     `pandoc --print-default-data-file=templates/styles.html`).-    Unless you use [`--css`](#option--css), this variable+    Unless you use `--css`, this variable     is set to `true` by default. You can disable it with     e.g. `pandoc -M document-css=false`. @@ -2746,9 +2761,9 @@ ### Variables for HTML math  `classoption`-:   when using [KaTeX](#option--katex), you can render display-math equations flush left using [YAML metadata](#layout) or with-`-M classoption=fleqn`.+:   when using `--katex`, you can render display math equations+    flush left using [YAML metadata](#layout) or with `-M+    classoption=fleqn`.  ### Variables for HTML slides @@ -2984,14 +2999,14 @@     Font fallbacks currently only work with `lualatex`.  `babelfonts`-:    a map of Babel language names (e.g. `chinese`) to the font-     to be used with the language:+:   a map of Babel language names (e.g. `chinese`) to the font+    to be used with the language: -     ----     babelfonts:-       chinese-hant: "Noto Serif CJK TC"-       russian: "Noto Serif"-     ...+        ---+        babelfonts:+          chinese-hant: "Noto Serif CJK TC"+          russian: "Noto Serif"+        ...  `microtypeoptions` :    options to pass to the microtype package@@ -3198,6 +3213,15 @@ `section` :   section number in man pages +### Variables for Texinfo++`version`+:   version of software (used in title and title page)++`filename`+:   name of info file to be generated (defaults to a name based on the+    texi filename)+ ### Variables for Typst  `margin`@@ -3339,7 +3363,7 @@  ## Typography -#### Extension: `smart` ####+### Extension: `smart` ###  Interpret straight quotes as curly quotes, `---` as em-dashes, `--` as en-dashes, and `...` as ellipses. Nonbreaking spaces are@@ -3372,7 +3396,7 @@  ## Headings and sections -#### Extension: `auto_identifiers` ####+### Extension: `auto_identifiers` ###  A heading without an explicitly specified identifier will be automatically assigned a unique identifier based on the heading text.@@ -3439,13 +3463,13 @@ sections to be manipulated using JavaScript or treated differently in CSS. -#### Extension: `ascii_identifiers` ####+### Extension: `ascii_identifiers` ###  Causes the identifiers produced by `auto_identifiers` to be pure ASCII. Accents are stripped off of accented Latin letters, and non-Latin letters are omitted. -#### Extension: `gfm_auto_identifiers` ####+### Extension: `gfm_auto_identifiers` ###  Changes the algorithm used by `auto_identifiers` to conform to GitHub's method.  Spaces are converted to dashes (`-`),@@ -3506,7 +3530,7 @@  ## Literate Haskell support -#### Extension: `literate_haskell` ####+### Extension: `literate_haskell` ###  Treat the document as literate Haskell source. @@ -3567,7 +3591,7 @@  ## Other extensions -#### Extension: `empty_paragraphs` ####+### Extension: `empty_paragraphs` ###  Allows empty paragraphs.  By default empty paragraphs are omitted.@@ -3580,7 +3604,7 @@ output formats :  `docx`, `odt`, `opendocument`, `html`, `latex` -#### Extension: `native_numbering` ####+### Extension: `native_numbering` ###  Enables native numbering of figures and tables. Enumeration starts at 1.@@ -3590,7 +3614,7 @@ output formats :  `odt`, `opendocument`, `docx` -#### Extension: `xrefs_name` ####+### Extension: `xrefs_name` ###  Links to headings, figures and tables inside the document are substituted with cross-references that will use the name or caption@@ -3607,7 +3631,7 @@ output formats :  `odt`, `opendocument` -#### Extension: `xrefs_number` ####+### Extension: `xrefs_number` ###  Links to headings, figures and tables inside the document are substituted with cross-references that will use the number@@ -3627,7 +3651,7 @@ output formats :  `odt`, `opendocument` -#### Extension: `styles` #### {#ext-styles}+### Extension: `styles` ### {#ext-styles}  When converting from docx, read all docx styles as divs (for paragraph styles) and spans (for character styles) regardless@@ -3638,12 +3662,12 @@ input formats :  `docx` -#### Extension: `amuse` ####+### Extension: `amuse` ###  In the `muse` input format, this enables Text::Amuse extensions to Emacs Muse markup. -#### Extension: `raw_markdown` ####+### Extension: `raw_markdown` ###  In the `ipynb` input format, this causes Markdown cells to be included as raw Markdown blocks (allowing lossless@@ -3674,14 +3698,14 @@ Note that for Org, this does not include roman numerals or the `#` placeholder that are enabled by the extension in Pandoc's Markdown. -#### Extension: `element_citations` ####+### Extension: `element_citations` ###  In the `jats` output formats, this causes reference items to be replaced with `<element-citation>` elements. These elements are not influenced by CSL styles, but all information on the item is included in tags. -#### Extension: `ntb` ####+### Extension: `ntb` ###  In the `context` output format this enables the use of [Natural Tables (TABLE)](https://wiki.contextgarden.net/TABLE) instead of the default@@ -3689,7 +3713,7 @@ Natural tables allow more fine-grained global customization but come at a performance penalty compared to extreme tables. -#### Extension: `tagging` ####+### Extension: `tagging` ### {#extension--tagging}  Enabling this extension with `context` output will produce markup suitable for the production of tagged PDFs. This includes@@ -3735,7 +3759,7 @@ Newlines are treated as spaces, so you can reflow your paragraphs as you like. If you need a hard line break, put two or more spaces at the end of a line. -#### Extension: `escaped_line_breaks` ####+### Extension: `escaped_line_breaks` ###  A backslash followed by a newline is also a hard line break. Note:  in multiline and grid table cells, this is the only way@@ -3775,7 +3799,7 @@      # A level-one heading with a [link](/url) and *emphasis* -#### Extension: `blank_before_header` ####+### Extension: `blank_before_header` ###  Original Markdown syntax does not require a blank line before a heading. Pandoc does require this (except, of course, at the beginning of the@@ -3786,7 +3810,7 @@     I like several of their flavors of ice cream:     #22, for example, and #5. -#### Extension: `space_in_atx_header` ####+### Extension: `space_in_atx_header` ###  Many Markdown implementations do not require a space between the opening `#`s of an ATX heading and the heading text, so that@@ -3798,7 +3822,7 @@ See also the [`auto_identifiers` extension](#extension-auto_identifiers) above. -#### Extension: `header_attributes` ####+### Extension: `header_attributes` ###  Headings can be assigned attributes using this syntax at the end of the line containing the heading text:@@ -3839,7 +3863,7 @@ (Currently this feature is only implemented for certain formats: those based on LaTeX and HTML, PowerPoint, and RTF.) -#### Extension: `implicit_header_references` ####+### Extension: `implicit_header_references` ###  Pandoc behaves as if reference links have been defined for each heading. So, to link to a heading@@ -3916,7 +3940,7 @@      >     code -#### Extension: `blank_before_blockquote` ####+### Extension: `blank_before_blockquote` ###  Original Markdown syntax does not require a blank line before a block quote.  Pandoc does require this (except, of course, at@@ -3950,7 +3974,7 @@  ### Fenced code blocks ### -#### Extension: `fenced_code_blocks` ####+### Extension: `fenced_code_blocks` ###  In addition to standard indented code blocks, pandoc supports *fenced* code blocks.  These begin with a row of three or more@@ -3976,12 +4000,12 @@     ~~~~~~~~~~     ~~~~~~~~~~~~~~~~ -#### Extension: `backtick_code_blocks` ####+### Extension: `backtick_code_blocks` ###  Same as `fenced_code_blocks`, but uses backticks (`` ` ``) instead of tildes (`~`). -#### Extension: `fenced_code_attributes` ####+### Extension: `fenced_code_attributes` ###  Optionally, you may attach attributes to fenced or backtick code block using this syntax:@@ -4052,7 +4076,7 @@  ## Line blocks -#### Extension: `line_blocks` ####+### Extension: `line_blocks` ###  A line block is a sequence of lines beginning with a vertical bar (`|`) followed by a space.  The division into lines will be preserved in@@ -4192,7 +4216,7 @@     7.  two     1.  three -#### Extension: `fancy_lists` ####+### Extension: `fancy_lists` ###  Unlike original Markdown, pandoc allows ordered list items to be marked with uppercase and lowercase letters and roman numerals, in addition to@@ -4225,7 +4249,7 @@  Note:  the '`#`' ordered list marker doesn't work with `commonmark`. -#### Extension: `startnum` ####+### Extension: `startnum` ###  Pandoc also pays attention to the type of list marker used, and to the starting number, and both of these are preserved where possible in the@@ -4254,7 +4278,7 @@     #.  two     #.  three -#### Extension: `task_lists` ####+### Extension: `task_lists` ###  Pandoc supports task lists, using the syntax of GitHub-Flavored Markdown. @@ -4263,7 +4287,7 @@  ### Definition lists ### -#### Extension: `definition_lists` ####+### Extension: `definition_lists` ###  Pandoc supports definition lists, using the syntax of [PHP Markdown Extra] with some extensions.[^3]@@ -4323,7 +4347,7 @@  ### Numbered example lists ### -#### Extension: `example_lists` ####+### Extension: `example_lists` ###  The special list marker `@` can be used for sequentially numbered examples. The first list item with a `@` marker will be numbered '1',@@ -4426,14 +4450,14 @@ a fixed-width font, such as Courier. The fourth kind can be used with proportionally spaced fonts, as it does not require lining up columns. -#### Extension: `table_captions` ####+### Extension: `table_captions` ###  A caption may optionally be provided with all 4 kinds of tables (as illustrated in the examples below). A caption is a paragraph beginning with the string `Table:` (or `table:` or just `:`), which will be stripped off. It may appear either before or after the table. -#### Extension: `simple_tables` ####+### Extension: `simple_tables` ###  Simple tables look like this: @@ -4477,7 +4501,7 @@ of the first line of the table body. So, in the tables above, the columns would be right, left, center, and right aligned, respectively. -#### Extension: `multiline_tables` ####+### Extension: `multiline_tables` ###  Multiline tables allow header and table rows to span multiple lines of text (but cells that span multiple columns or rows of the table are@@ -4527,7 +4551,7 @@ should be followed by a blank line (and then the row of dashes that ends the table), or the table may be interpreted as a simple table. -#### Extension: `grid_tables` ####+### Extension: `grid_tables` ###  Grid tables look like this: @@ -4607,7 +4631,7 @@ Grid tables can be created easily using Emacs' table-mode (`M-x table-insert`). -#### Extension: `pipe_tables` ####+### Extension: `pipe_tables` ###  Pipe tables look like this: @@ -4663,7 +4687,7 @@  ## Metadata blocks -#### Extension: `pandoc_title_block` ####+### Extension: `pandoc_title_block` ###  If the file begins with a title block @@ -4751,7 +4775,7 @@  will also have "Version 4.0" in the header. -#### Extension: `yaml_metadata_block` ####+### Extension: `yaml_metadata_block` ###  A [YAML] metadata block is a valid YAML object, delimited by a line of three hyphens (`---`) at the top and a line of three hyphens (`---`) or three dots@@ -4884,7 +4908,7 @@  ## Backslash escapes -#### Extension: `all_symbols_escapable` ####+### Extension: `all_symbols_escapable` ###  Except inside a code block or inline code, any punctuation or space character preceded by a backslash will be treated literally, even if it@@ -4941,7 +4965,7 @@      This is * not emphasized *, and \*neither is this\*. -#### Extension: `intraword_underscores` ####+### Extension: `intraword_underscores` ###  Because `_` is sometimes used inside words and identifiers, pandoc does not interpret a `_` surrounded by alphanumeric@@ -4952,7 +4976,7 @@  ### Strikeout ### -#### Extension: `strikeout` ####+### Extension: `strikeout` ###  To strike out a section of text with a horizontal line, begin and end it with `~~`. Thus, for example,@@ -4962,7 +4986,7 @@  ### Superscripts and subscripts ### -#### Extension: `superscript`, `subscript` ####+### Extension: `superscript`, `subscript` ###  Superscripts may be written by surrounding the superscripted text by `^` characters; subscripts may be written by surrounding the subscripted@@ -5001,7 +5025,7 @@      This is a backslash followed by an asterisk: `\*`. -#### Extension: `inline_code_attributes` ####+### Extension: `inline_code_attributes` ###  Attributes can be attached to verbatim text, just as with [fenced code blocks]:@@ -5051,7 +5075,7 @@  ## Math -#### Extension: `tex_math_dollars` ####+### Extension: `tex_math_dollars` ###  Anything between two `$` characters will be treated as TeX math.  The opening `$` must have a non-space character immediately to its right,@@ -5128,7 +5152,7 @@  ## Raw HTML -#### Extension: `raw_html` ####+### Extension: `raw_html` ###  Markdown allows you to insert raw HTML (or DocBook) anywhere in a document (except verbatim contexts, where `<`, `>`, and `&` are interpreted@@ -5149,7 +5173,7 @@ `raw_html` is disabled, tables will be rendered with HTML syntax if they cannot use pipe syntax. -#### Extension: `markdown_in_html_blocks` ####+### Extension: `markdown_in_html_blocks` ###  Original Markdown allows you to include HTML "blocks":  blocks of HTML between balanced tags that are separated from the surrounding text@@ -5187,21 +5211,21 @@ a block of Markdown text with `<div>` tags without preventing it from being interpreted as Markdown. -#### Extension: `native_divs` ####+### Extension: `native_divs` ###  Use native pandoc `Div` blocks for content inside `<div>` tags. For the most part this should give the same output as `markdown_in_html_blocks`, but it makes it easier to write pandoc filters to manipulate groups of blocks. -#### Extension: `native_spans` ####+### Extension: `native_spans` ###  Use native pandoc `Span` blocks for content inside `<span>` tags. For the most part this should give the same output as `raw_html`, but it makes it easier to write pandoc filters to manipulate groups of inlines. -#### Extension: `raw_tex` ####+### Extension: `raw_tex` ###  In addition to raw HTML, pandoc allows raw LaTeX, TeX, and ConTeXt to be included in a document. Inline TeX commands will be preserved and passed@@ -5231,7 +5255,7 @@  ### Generic raw attribute ### -#### Extension: `raw_attribute` ####+### Extension: `raw_attribute` ###  Inline spans and fenced code blocks with a special kind of attribute will be parsed as raw content with the@@ -5274,7 +5298,7 @@  ## LaTeX macros -#### Extension: `latex_macros` ####+### Extension: `latex_macros` ###  When this extension is enabled, pandoc will parse LaTeX macro definitions and apply the resulting macros to all LaTeX@@ -5382,7 +5406,7 @@     >     > [quote]: /foo -#### Extension: `shortcut_reference_links` ####+### Extension: `shortcut_reference_links` ###  In a *shortcut* reference link, the second pair of brackets may be omitted entirely:@@ -5418,7 +5442,7 @@      [movie reel]: movie.gif -#### Extension: `implicit_figures` ####+### Extension: `implicit_figures` ###  An image with nonempty alt text, occurring by itself in a paragraph, will be rendered as a figure with a caption.  The@@ -5441,7 +5465,7 @@ by itself that has the `r-stretch` class will fill the screen, and the caption and figure tags will be omitted. -#### Extension: `link_attributes` ####+### Extension: `link_attributes` ###  Attributes can be set on links and images: @@ -5497,7 +5521,7 @@ elements in the pandoc AST (as opposed to raw HTML). However, there is also nicer syntax available: -#### Extension: `fenced_divs` ####+### Extension: `fenced_divs` ###  Allow special fenced syntax for native `Div` blocks.  A Div starts with a fence containing at least three consecutive@@ -5541,7 +5565,7 @@ lengths to distinguish nested divs from their parents.  -#### Extension: `bracketed_spans` ####+### Extension: `bracketed_spans` ###  A bracketed sequence of inlines, as one would use to begin a link, will be treated as a `Span` with attributes if it is@@ -5551,7 +5575,7 @@  ## Footnotes -#### Extension: `footnotes` ####+### Extension: `footnotes` ###  Pandoc's Markdown allows footnotes, using the following syntax: @@ -5584,7 +5608,7 @@ separated from surrounding content (including other footnotes) by blank lines. -#### Extension: `inline_notes` ####+### Extension: `inline_notes` ###  Inline footnotes are also allowed (though, unlike regular notes, they cannot contain multiple paragraphs).  The syntax is as follows:@@ -5597,7 +5621,7 @@  ## Citation syntax -#### Extension: `citations` ####+### Extension: `citations` ###  To cite a bibliographic item with an identifier foo, use the syntax `@foo`.  Normal citations should be included in square@@ -5706,7 +5730,7 @@ name, where `EXTENSION` is the name of the extension.  Thus, for example, `markdown+hard_line_breaks` is Markdown with hard line breaks. -#### Extension: `rebase_relative_paths` ####+### Extension: `rebase_relative_paths` ###  Rewrite relative paths for Markdown links and images, depending on the path of the file containing the link or image link.  For@@ -5737,14 +5761,14 @@ reference definition, not the file containing the reference link or image itself, if these differ. -#### Extension: `mark` ####+### Extension: `mark` ###  To highlight out a section of text, begin and end it with with `==`. Thus, for example,      This ==is deleted text.== -#### Extension: `attributes` ####+### Extension: `attributes` ###  Allows attributes to be attached to any inline or block-level element when parsing `commonmark`.@@ -5776,50 +5800,50 @@ to be attached to arbitrary elements.  Hence a Span or Div container will be added if needed. -#### Extension: `old_dashes` ####+### Extension: `old_dashes` ###  Selects the pandoc <= 1.8.2.1 behavior for parsing smart dashes: `-` before a numeral is an en-dash, and `--` is an em-dash. This option only has an effect if `smart` is enabled. It is selected automatically for `textile` input. -#### Extension: `angle_brackets_escapable` ####+### Extension: `angle_brackets_escapable` ###  Allow `<` and `>` to be backslash-escaped, as they can be in GitHub flavored Markdown but not original Markdown.  This is implied by pandoc's default `all_symbols_escapable`. -#### Extension: `lists_without_preceding_blankline` ####+### Extension: `lists_without_preceding_blankline` ###  Allow a list to occur right after a paragraph, with no intervening blank space. -#### Extension: `four_space_rule` ####+### Extension: `four_space_rule` ###  Selects the pandoc <= 2.0 behavior for parsing lists, so that four spaces indent are needed for list item continuation paragraphs. -#### Extension: `spaced_reference_links` ####+### Extension: `spaced_reference_links` ###  Allow whitespace between the two components of a reference link, for example,      [foo] [bar]. -#### Extension: `hard_line_breaks` ####+### Extension: `hard_line_breaks` ###  Causes all newlines within a paragraph to be interpreted as hard line breaks instead of spaces. -#### Extension: `ignore_line_breaks` ####+### Extension: `ignore_line_breaks` ###  Causes newlines within a paragraph to be ignored, rather than being treated as spaces or as hard line breaks.  This option is intended for use with East Asian languages where spaces are not used between words, but text is divided into lines for readability. -#### Extension: `east_asian_line_breaks` ####+### Extension: `east_asian_line_breaks` ###  Causes newlines within a paragraph to be ignored, rather than being treated as spaces or as hard line breaks, when they occur@@ -5827,11 +5851,11 @@ than `ignore_line_breaks` for texts that include a mix of East Asian wide characters and other characters. -#### Extension: `emoji` ####+### Extension: `emoji` ###  Parses textual emojis like `:smile:` as Unicode emoticons. -#### Extension: `tex_math_gfm` ####+### Extension: `tex_math_gfm` ###  Supports two GitHub-specific formats for math. Inline math: ``$`e=mc^2`$``.@@ -5844,26 +5868,26 @@ ``` ```` -#### Extension: `tex_math_single_backslash` ####+### Extension: `tex_math_single_backslash` ###  Causes anything between `\(` and `\)` to be interpreted as inline TeX math, and anything between `\[` and `\]` to be interpreted as display TeX math.  Note: a drawback of this extension is that it precludes escaping `(` and `[`. -#### Extension: `tex_math_double_backslash` ####+### Extension: `tex_math_double_backslash` ###  Causes anything between `\\(` and `\\)` to be interpreted as inline TeX math, and anything between `\\[` and `\\]` to be interpreted as display TeX math. -#### Extension: `markdown_attribute` ####+### Extension: `markdown_attribute` ###  By default, pandoc interprets material inside block-level tags as Markdown. This extension changes the behavior so that Markdown is only parsed inside block-level tags if the tags have the attribute `markdown=1`. -#### Extension: `mmd_title_block` ####+### Extension: `mmd_title_block` ###  Enables a [MultiMarkdown] style title block at the top of the document, for example:@@ -5878,7 +5902,7 @@ `yaml_metadata_block` is enabled, it will take precedence over `mmd_title_block`. -#### Extension: `abbreviations` ####+### Extension: `abbreviations` ###  Parses PHP Markdown Extra abbreviation keys, like @@ -5888,21 +5912,21 @@ abbreviations, so if this extension is enabled, abbreviation keys are simply skipped (as opposed to being parsed as paragraphs). -#### Extension: `alerts` ####+### Extension: `alerts` ###  Supports [GitHub-style Markdown alerts], like -    > [!INFO]-    > This is an informational message.+    > [!TIP]+    > Helpful advice for doing things better or more easily.    [GitHub-style Markdown alerts]: https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts -#### Extension: `autolink_bare_uris` ####+### Extension: `autolink_bare_uris` ###  Makes all absolute URIs into links, even when not surrounded by pointy braces `<...>`. -#### Extension: `mmd_link_attributes` ####+### Extension: `mmd_link_attributes` ###  Parses MultiMarkdown-style key-value attributes on link and image references. This extension should not be confused with the@@ -5913,12 +5937,12 @@     [ref]: https://path.to/image "Image title" width=20px height=30px            id=myId class="myClass1 myClass2" -#### Extension: `mmd_header_identifiers` ####+### Extension: `mmd_header_identifiers` ###  Parses MultiMarkdown-style heading identifiers (in square brackets, after the heading but before any trailing `#`s in an ATX heading). -#### Extension: `compact_definition_lists` ####+### Extension: `compact_definition_lists` ###  Activates the definition list syntax of pandoc 1.12.x and earlier. This syntax differs from the one described above under [Definition lists]@@ -5945,7 +5969,7 @@     we must either disallow lazy wrapping or require a blank line between     list items. -#### Extension: `gutenberg` ####+### Extension: `gutenberg` ###  Use [Project Gutenberg] conventions for `plain` output: all-caps for strong emphasis, surround by underscores@@ -5953,14 +5977,14 @@    [Project Gutenberg]: https://www.gutenberg.org -#### Extension: `sourcepos` ####+### Extension: `sourcepos` ###  Include source position attributes when parsing `commonmark`. For elements that accept attributes, a `data-pos` attribute is added; other elements are placed in a surrounding Div or Span element with a `data-pos` attribute. -#### Extension: `short_subsuperscripts` ####+### Extension: `short_subsuperscripts` ###  Parse MultiMarkdown-style subscripts and superscripts, which start with a '~' or '^' character, respectively, and include the alphanumeric sequence@@ -5972,7 +5996,7 @@      Oxygen is O~2. -#### Extension: `wikilinks_title_after_pipe` ####+### Extension: `wikilinks_title_after_pipe` ###  Pandoc supports multiple Markdown wikilink syntaxes, regardless of whether the title is before or after the pipe.@@ -6657,6 +6681,8 @@     :::     :::::::::::::: +Note: Specifying column widths does not currently work for PowerPoint.+ ### Additional columns attributes in beamer  The div containers with classes `columns` and `column` can optionally have@@ -6729,7 +6755,7 @@ Note that for reveal.js, the `background-image` will be used as a `parallaxBackgroundImage` (see below). -For pptx, you can use a [reference doc](#option--reference-doc) in which+For pptx, you can use a `--reference-doc` in which background images have been set on the [relevant layouts](#powerpoint-layout-choice). @@ -6770,7 +6796,7 @@ It must contain a map of attribute names and values. (Note that the `data-` prefix is required here, as it isn’t added automatically.) -For pptx, pass a [reference doc](#option--reference-doc) with the background+For pptx, pass a `--reference-doc` with the background image set on the “Title Slide” layout.  ### Example (reveal.js)@@ -7209,7 +7235,7 @@ By default, pandoc's odt, docx and ICML output applies a predefined set of styles for blocks such as paragraphs and block quotes, and uses largely default formatting (italics, bold) for inlines. This will work for most-purposes, especially alongside a [reference doc]{#option--reference-doc} file.+purposes, especially alongside a [reference doc](#option--reference-doc) file. However, if you need to apply your own styles to blocks, or match a preexisting set of styles, pandoc allows you to define custom styles for blocks and text using `div`s and `span`s, respectively.@@ -7236,7 +7262,7 @@  Styles will be defined in the output file as inheriting from normal text (docx) or Default Paragraph Style (odt), if the-styles are not yet in your [reference doc]{#option--reference-doc}.+styles are not yet in your [reference doc](#option--reference-doc). If they are already defined, pandoc will not alter the definition.  This feature allows for greatest customization in conjunction with@@ -7455,7 +7481,6 @@ `lua` as the first argument will make it function as a standalone Lua interpreter. The behavior is mostly identical to that of the [standalone `lua` executable][lua standalone], version 5.4.-However, there is no REPL yet, and the `-i` option has no effect. For full documentation, see the [pandoc-lua] man page.  [lua standalone]: https://www.lua.org/manual/5.4/manual.html#7
changelog.md view
@@ -1,5 +1,293 @@ # Revision history for pandoc +## pandoc 3.2.1 (2024-06-24)++  * Fix `gfm_auto_identifiers` to replace emojis with their aliases,+    as documented (#9876).++  * CSV reader:++    + Turn line breaks into LineBreaks not SoftBreaks (#9797).++  * Docx reader:++    + Support task lists (#8211).+    + Fix a small bug in parsing delimiters in numbered lists,+      which led to the default delimiter being used wrongly in some cases.+    + Improve handling of captions.+      - Turn captioned images into Figure elements. Closes #9391.+      - Improve the logic for associating elements with captions (#9358).+      - Ensure that captions that can't be associated with an+        element aren't just silently dropped (#9610).+    + Support HorizontalRule. We support both pandoc-style and the style+      described on a Microsoft support page, an empty paragraph with+      a bottom border (#6285).+    + React to `"left"` value on `jc` attribute.+    + Handle column and cell alignments (#8551). We take the column alignments+      from the first body row.+    + Fix a bug that caused comments inside insertions or deletions+      to be ignored (#9833).++  * HTML reader:++    + Better handle non-`li` elements in `ul` and `ol` (#9809).+      For example, a `p` after a closed `li` will be incorporated into+      the previous `li`. This mirrors what browsers do with this+      invalid HTML.++  * LaTeX reader:++    + Fix parsing of dimensions beginning with `.`, e.g. `\kern.1pt` (#9902).++  * Markdown reader:++    + Allow author-only textual citations (#7219). E.g. `-@reese2002`+      outside of brackets.++  * RST reader:++    + Tighten up rules for when emphasis can start (#9805).+    + Support `:cite:` role with citeproc (#9904). A subset of the+      functionality of the sphinxcontrib-bibtex extension to Sphinx+      is supported.++  * Textile reader:++    + Don't let spans begin right after a symbol (#9878).++  * Texinfo writer:++    + Ensure proper escaping in all node/link contexts.+    + Target node rather than anchor when possible in internal links.+    + Remove illegal characters from internal link anchors (#6177).+    + Use two commas not one in `@ref`.+    + Don't add anchors to headings. We don't need them, now that we+      make internal links use the node.+    + Avoid duplicate node names.+    + Improve menus. Properly handle the case where the node name is+      different from the descriptive title.++  * Texinfo template: add variables for filename and version.++  * Typst reader:++    + Fix an incomplete pattern match (#9807).+    + Handle inline bodies ending in a parbreak. E.g.+      ```+      `#strong[+      test+      ]+      ```++  * ConTeXt template: remove `\setupbackend[export=yes]` (#9820).++  * Docx writer:++    + Omit `jc` attribute on table cells with AlignDefault (#5662).+    + Better formatting for task lists. Task lists are now properly+      formatted, with no bullet (#5198).+    + Replace an expensive generic traverse to remove Space elements,+      for better performance.+    + 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.+    + Wrap figures with `id` in a bookmark (#8662).+    + Add eastAsia font hints to `w:r` (#9817). 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.+    + Clean up Abstract Title and Subtitle in default reference docx.+      Center Subtitle, remove color.+    + Allow OpenXML templates to be used with `docx` (#8338, #9069, #7256,+      #2928). 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.) `--include-before-body` and+      `--include-after-body` can also now be used with `docx` output.+      The included files must be OpenXML fragments suitable for+      inclusion in the document body.+    + New unexported module Text.Pandoc.Writers.Docx.OpenXML.++  * HTML writer:++    + Ensure URI escaping needed for `html4` (#9905).+      Unicode characters need not be escaped for html5, and still won't be.++    + Don't emit unnecessary classes in HTML tables (#9325, Thomas Soeiro).+      Pandoc used to emit a `header` class on the `tr` element that forms+      the table header. This is no longer needed, because `head > tr` will+      do the same thing. Similarly, pandoc used to emit `even` and `odd`+      classes on `tr`s, allowing striped styling.  This is no longer needed,+      because one can use e.g. `tbody tr:nth-child(2n)`.++      Compatibility warning:  users who relied on these classes to style+      tables may need to adjust their CSS.++  * JATS writer:++    + Support `supplementary-material` in metadata for `jats_articlepublishing`+      (#9818).++  * LaTeX writer:++    + New method for ensuring images don't overflow (#9660).+      Previously we relied on graphicx internals and made global+      changes to Gin to force images to be resized if they exceed+      textwidth.  This approach is brittle and caused problems+      with `\includesvg` (see #9660). The new approach uses a new macro+      `\pandocbounded` that is now defined in the LaTeX template.+      (Thanks here to Falk Hanisch in https://github.com/mrpiggi/svg/issues/60.)+      The LaTeX writer has been changed to enclose `\includegraphics`+      and `\includesvg` commands in this macro when they don't explicitly+      specify a width or height. In addition, the writer now adds+      `keepaspectratio` to the `\includegraphics` or `\includesvg`+      options if `height` is specified without width, or vice versa.+      Previously, this was set in the preamble as a global option.+      Users should attend to the following compatibility issues:+      - If custom templates are used with the new LaTeX writer, they will have+        to be updated to include the new `\pandocbounded` macro, or an error+        will be raised because of the undefined macro.+      - Documents that specify explicit dimensions for an image may render+        differently, if the dimensions are greater than the line width or+        page height. Previously pandoc would shrink these images to fit,+        but the new behavior takes the specified dimensions literally.+        In addition, pandoc previously always enforced `keepaspectratio`,+        even when width and height were both specified, so images with+        width and height specified that do not conform to their intrinsic+        aspect ratio will appear differently.+    + Task lists must be unordered (#9185).+    + Specify language option for `selnolig` and only include it if+      `english` or `german` is used (#9863). (This includes changes to the+      LaTeX template.) This should restore proper ligature suppression when+      lualatex is used.+    + Fix `--toc-depth` with beamer output (#9861). Previously only top-level+      sections were ever included in the TOC, regardless of the setting of+      `--toc-depth`.+    + Use `\linewidth` instead of `\columnwidth` or `\textwidth`+      for resizing figures, table cells, etc. in LaTeX (#9775).+      `\linewidth`, unlike the others, is sensitive to indented environments+      like lists.++  * LaTeX template: put `babel-lang` in options to beamer (#9868).+    This is required to make beamer use proper localized terms for+    things like "Section."++  * Markdown writer:++    + Don't print extra caption when using `implicit_figures`.+    + Ensure blank line after HTML blocks in commonmark-based formats (#9792).+    + Fix bug rendering block quotes in lists (#9908).++  * Typst writer:++    + Support '.typst:no-figure' and 'typst:figure:kind=kind' attributes+      (#9778, Carlos Scheidegger). This extends support for fine-grained+      properties in Typst. If the `typst:no-figure` class is present on a+      Table, the table will not be placed in a figure. If the+      `typst:figure:kind` attribute is present, its value will be used+      for the figure's `kind` (#9777). These features are documented in+      `doc/typst-property-output.md`.++  * Typst template:++    + Add subtitle (#9747, Mickaël Canouil).+    + Use content rather than string for title, author, date, email (#9823).+      This allows formatting in title, author, date, and email fields.+      Since the PDF metadata requires a string, and typst only+      converts the title to a string (not the authors), we use++  * Textile writer:++    + Get rid of header, odd, even classes on `tr` (#9376).++  * Text.Pandoc.Class:++    + `fillMediaBag`: Convert IOErrors to warnings when fetching absolute+       paths (#9859, Albert Krewinkel).  This will allow many conversions that+       would have failed with an error to succeed (albeit without images or+       other needed resources).++  * Text.Pandoc.ImageSize:++    + Don't prefer exif width/height when they conflict with image+      width/height (#9871).  That was a mistaken call in #6936.+      Usually when these values disagree, it is because the image+      has been resized by a tool that leaves the original exif values+      the same, so the width/height metadata are more likely to be+      correct that exif width/height.++  * Text.Pandoc.SelfContained:++    + Strip CRs from XML before base64 encoding for data URI+      (so tests can work on Windows).+    + Only create `<svg>` elements for SVG images when the image has+      the class `inline-svg`. Otherwise just use a `data` URI as we do+      with other images (#9787).++  * Lua subsystem (Albert Krewinkel):++    + Split Init module into more modules. The module has grown unwieldy and+      is therefore split into three internal Haskell modules, `Init`,+      `Module`, and `Run`.+    + Add function `pandoc.utils.run_lua_filter` (#9803).+    + Add function `pandoc.template.get` (#9854, co-authored by Carsten Gips).+      The function allows to specify a template with the same argument value+      that would be used with the `--template` command line parameter.+    + Keep CommonState object in the registry. The state is an internal+      value and should be treated as such. The `PANDOC_STATE` global is+      merely a copy; unsetting the global no longer breaks the Lua engine.+    + Allow passing an environment to `run_lua_filter`.+      The default is now to use a *copy* of the global environment when running+      a filter; this ensures better separation when `run_lua_filter` is used+      multiple times. A custom environment can be specified via the+      optional third parameter.+    + Set `pandoc.List` as default metatable for JSON lists (#9834).+      Lists created by `pandoc.json.decode` now behave like lists generated+      via `pandoc.List`. This also ensures that `pandoc.List` tables are+      encoded as JSON arrays when passed to `pandoc.json.encode`.++  * Text.Pandoc.Writers.Shared: export `toTaskListItem` [API change].++  * Add unexported module Text.Pandoc.Char. This exports `isCJK`.+    Use this instead of locally defined `isCJK` in T.P.Readers.MediaWiki.++  * MANUAL.txt:++    + Remove false claim that Lua mode does not support `-i` (#9757,+      Ian Max Andolina).+    + Use level-3 headings for extensions (to avoid gaps).+    + Add anchor for tagging extension.+    + Remove explicit referencess to generate anchors.+      These will be linkified automatically.+    + Fixed links to `option--reference-doc`.+    + Add a note that column widths aren't supported in pptx for Divs+      with class `columns` (#9890).+    + Fix alerts example (#9826, Ian Max Andolina).+    + Fix markup of `babelfonts` example code (Albert Krewinkel).++  * `doc/custom-writers.md`:++    + Fix usage of Template in example (Albert Krewinkel).+    + Document the separator arg of `Writer.Blocks` (Albert Krewinkel).++  * `doc/lua-filters.md` (Albert Krewinkel):++    + Fix outdated documentation for math and quoting functions and fields.+    + Autogenerate docs for module `pandoc.template` and `pandoc.layout`.+    + Document operators of the "Doc" type.++  * pandoc-lua-engine: depend on pandoc >= 3.2 (see #9755).++  * Allow crypton-connection 0.4, time 1.14.++  * Allow tasty-quickcheck 0.11.++  * Use latest emojis, skylighting, skylighting-core, citeproc, djot,+    commonmark-extensions, typst-hs+ ## pandoc 3.2 (2024-05-11)    * Change to `--file-scope` behavior (#8741): previously a Div with an
data/docx/word/styles.xml view
@@ -85,7 +85,7 @@   </w:style>   <w:style w:type="paragraph" w:styleId="Subtitle">     <w:name w:val="Subtitle" />-    <w:basedOn w:val="Normal" />+    <w:basedOn w:val="Title" />     <w:next w:val="BodyText" />     <w:link w:val="SubtitleChar" />     <w:uiPriority w:val="11" />@@ -99,8 +99,6 @@     <w:rPr>       <w:rFonts w:eastAsiaTheme="majorEastAsia"       w:cstheme="majorBidi" />-      <w:color w:val="595959" w:themeColor="text1"-      w:themeTint="A6" />       <w:spacing w:val="15" />       <w:sz w:val="28" />       <w:szCs w:val="28" />@@ -156,7 +154,6 @@     </w:pPr>     <w:rPr>       <w:b />-      <w:color w:val="345A8A" />       <w:sz w:val="20" />       <w:szCs w:val="20" />     </w:rPr>
data/templates/default.context view
@@ -47,7 +47,6 @@    profile={$if(pdfaiccprofile)$$for(pdfaiccprofile)$$pdfaiccprofile$$sep$,$endfor$$else$sRGB.icc$endif$},    intent=$if(pdfaintent)$$pdfaintent$$else$sRGB IEC61966-2.1$endif$] $endif$-\setupbackend[export=yes] \setupstructure[state=start,method=auto]  % use microtypography
data/templates/default.jats_articleauthoring view
@@ -91,6 +91,11 @@ <funding-statement>$article.funding-statement$</funding-statement> </funding-group> $endif$+$if(supplementary-material)$+<supplementary-material>+$supplementary-material$+</supplementary-material>+$endif$ </article-meta> </front> <body>
data/templates/default.latex view
@@ -23,7 +23,10 @@ $if(aspectratio)$   aspectratio=$aspectratio$, $endif$+$if(babel-lang)$+  $babel-lang$, $endif$+$endif$ $for(classoption)$   $classoption$$sep$, $endfor$@@ -299,15 +302,17 @@ $if(graphics)$ \usepackage{graphicx} \makeatletter-\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi}-\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi}-\makeatother-% Scale images if necessary, so that they will not overflow the page-% margins by default, and it is still possible to overwrite the defaults-% using explicit options in \includegraphics[width, height, ...]{}-\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio}+\newsavebox\pandoc@box+\newcommand*\pandocbounded[1]{% scales image to fit in text height/width+  \sbox\pandoc@box{#1}%+  \Gscale@div\@tempa{\textheight}{\dimexpr\ht\pandoc@box+\dp\pandoc@box\relax}%+  \Gscale@div\@tempb{\linewidth}{\wd\pandoc@box}%+  \ifdim\@tempb\p@<\@tempa\p@\let\@tempa\@tempb\fi% select the smaller of both+  \ifdim\@tempa\p@<\p@\scalebox{\@tempa}{\usebox\pandoc@box}%+  \else\usebox{\pandoc@box}%+  \fi%+} % Set default figure placement to htbp-\makeatletter \def\fps@figure{htbp} \makeatother $endif$@@ -440,13 +445,15 @@ % get rid of language-specific shorthands (see #6817): \let\LanguageShortHands\languageshorthands \def\languageshorthands#1{}+$if(selnolig-langs)$+\ifLuaTeX+  \usepackage[$for(selnolig-langs)$$it$$sep$,$endfor$]{selnolig} % disable illegal ligatures+\fi $endif$+$endif$ $for(header-includes)$ $header-includes$ $endfor$-\ifLuaTeX-  \usepackage{selnolig}  % disable illegal ligatures-\fi $if(dir)$ \ifPDFTeX   \TeXXeTstate=1@@ -571,7 +578,8 @@ $if(toc-title)$   \frametitle{$toc-title$} $endif$-  \tableofcontents[hideallsubsections]+  \setcounter{tocdepth}{$toc-depth$}+  \tableofcontents \end{frame} $else$ {
+ data/templates/default.openxml view
@@ -0,0 +1,64 @@+<?xml version="1.0" encoding="UTF-8"?>+<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing">+<w:body>+$if(title)$+    <w:p>+      <w:pPr>+        <w:pStyle w:val="Title" />+      </w:pPr>+      $title$+    </w:p>+$endif$+$if(subtitle)$+    <w:p>+      <w:pPr>+        <w:pStyle w:val="Subtitle" />+      </w:pPr>+      $subtitle$+    </w:p>+$endif$+$for(author)$+    <w:p>+      <w:pPr>+        <w:pStyle w:val="Author" />+      </w:pPr>+      $author$+    </w:p>+$endfor$+$if(date)$+    <w:p>+      <w:pPr>+        <w:pStyle w:val="Date" />+      </w:pPr>+      $date$+    </w:p>+$endif$+$if(abstract)$+$if(abstract-title)$+    <w:p>+      <w:pPr>+        <w:pStyle w:val="AbstractTitle" />+      </w:pPr>+      <w:r><w:t xml:space="preserve">$abstract-title$</w:t></w:r>+    </w:p>+$endif$+    $abstract$+$endif$+$for(include-before)$+    $include-before$+$endfor$+$if(toc)$+    $toc$+$endif$+    $body$+$for(include-after)$+    $include-after$+$endfor$+$-- sectpr will be set to the last sectpr in a reference.docx, if present+$if(sectpr)$+    $sectpr$+$else$+    <w:sectPr />+$endif$+  </w:body>+</w:document>
data/templates/default.texinfo view
@@ -1,4 +1,11 @@-\input texinfo+\input texinfo  @c -*-texinfo-*-+$if(filename)$+@setfilename $filename$+$endif$+$if(title)$+@settitle $title$$if(version)$ $version$$endif$+$endif$+ @documentencoding UTF-8 $for(header-includes)$ $header-includes$@@ -16,6 +23,9 @@ $if(titlepage)$ @titlepage @title $title$+$if(version)$+@subtitle $version$+$endif$ $for(author)$ @author $author$ $endfor$
data/templates/default.typst view
@@ -24,15 +24,18 @@ $if(title)$   title: [$title$], $endif$+$if(subtitle)$+  subtitle: [$subtitle$],+$endif$ $if(author)$   authors: ( $for(author)$ $if(author.name)$-    ( name: "$author.name$",-      affiliation: "$author.affiliation$",-      email: "$author.email$" ),+    ( name: [$author.name$],+      affiliation: [$author.affiliation$],+      email: [$author.email$] ), $else$-    ( name: "$author$",+    ( name: [$author$],       affiliation: "",       email: "" ), $endif$@@ -43,7 +46,7 @@   keywords: ($for(keywords)$$keyword$$sep$,$endfor$), $endif$ $if(date)$-  date: "$date$",+  date: [$date$], $endif$ $if(lang)$   lang: "$lang$",
data/templates/template.typst view
@@ -1,5 +1,17 @@+#let content-to-string(content) = {+  if content.has("text") {+    content.text+  } else if content.has("children") {+    content.children.map(content-to-string).join("")+  } else if content.has("body") {+    content-to-string(content.body)+  } else if content == [ ] {+    " "+  }+} #let conf(   title: none,+  subtitle: none,   authors: (),   keywords: (),   date: none,@@ -16,7 +28,7 @@ ) = {   set document(     title: title,-    author: authors.map(author => author.name),+    author: authors.map(author => content-to-string(author.name)),     keywords: keywords,   )   set page(@@ -34,6 +46,10 @@   if title != none {     align(center)[#block(inset: 2em)[       #text(weight: "bold", size: 1.5em)[#title]+      #(if subtitle != none {+        parbreak()+        text(weight: "bold", size: 1.25em)[#subtitle]+      })     ]]   } 
pandoc.cabal view
@@ -1,6 +1,6 @@ cabal-version:   2.4 name:            pandoc-version:         3.2+version:         3.2.1 build-type:      Simple license:         GPL-2.0-or-later license-file:    COPYING.md@@ -64,6 +64,7 @@                  data/templates/default.jats_publishing                  data/templates/default.tei                  data/templates/default.opendocument+                 data/templates/default.openxml                  data/templates/default.icml                  data/templates/default.opml                  data/templates/default.latex@@ -206,6 +207,8 @@                  test/command/*.md                  test/command/*.csl                  test/command/*.svg+                 test/command/9391.docx+                 test/command/9358.docx                  test/command/9002.docx                  test/command/biblio.bib                  test/command/averroes.bib@@ -477,18 +480,18 @@                  blaze-markup          >= 0.8      && < 0.9,                  bytestring            >= 0.9      && < 0.13,                  case-insensitive      >= 1.2      && < 1.3,-                 citeproc              >= 0.8.1    && < 0.9,+                 citeproc              >= 0.8.1.1  && < 0.9,                  commonmark            >= 0.2.6    && < 0.3,-                 commonmark-extensions >= 0.2.5.4  && < 0.3,+                 commonmark-extensions >= 0.2.5.5  && < 0.3,                  commonmark-pandoc     >= 0.2.2.1  && < 0.3,                  containers            >= 0.6.0.1  && < 0.8,-                 crypton-connection    >= 0.3.1    && < 0.4,+                 crypton-connection    >= 0.3.1    && < 0.5,                  data-default          >= 0.4      && < 0.8,                  deepseq               >= 1.3      && < 1.6,                  directory             >= 1.2.3    && < 1.4,                  doclayout             >= 0.4.0.1  && < 0.5,                  doctemplates          >= 0.11     && < 0.12,-                 emojis                >= 0.1      && < 0.2,+                 emojis                >= 0.1.4.1  && < 0.2,                  exceptions            >= 0.8      && < 0.11,                  file-embed            >= 0.0      && < 0.1,                  filepath              >= 1.1      && < 1.6,@@ -511,8 +514,8 @@                  random                >= 1        && < 1.3,                  safe                  >= 0.3.18   && < 0.4,                  scientific            >= 0.3      && < 0.4,-                 skylighting           >= 0.14.1.2 && < 0.15,-                 skylighting-core      >= 0.14.1.2 && < 0.15,+                 skylighting           >= 0.14.2   && < 0.15,+                 skylighting-core      >= 0.14.2   && < 0.15,                  split                 >= 0.2      && < 0.3,                  syb                   >= 0.1      && < 0.8,                  tagsoup               >= 0.14.6   && < 0.15,@@ -520,16 +523,16 @@                  texmath               >= 0.12.8.9 && < 0.13,                  text                  >= 1.1.1.0  && < 2.2,                  text-conversions      >= 0.3      && < 0.4,-                 time                  >= 1.5      && < 1.14,+                 time                  >= 1.5      && < 1.15,                  unicode-collation     >= 0.1.1    && < 0.2,                  unicode-transforms    >= 0.3      && < 0.5,                  yaml                  >= 0.11     && < 0.12,                  zip-archive           >= 0.4.3.1  && < 0.5,                  zlib                  >= 0.5      && < 0.8,                  xml                   >= 1.3.12   && < 1.4,-                 typst                 >= 0.5.0.3  && < 0.5.1,+                 typst                 >= 0.5.0.4  && < 0.5.1,                  vector                >= 0.12     && < 0.14,-                 djot                  >= 0.1.2    && < 0.2,+                 djot                  >= 0.1.2.1  && < 0.2,                  tls                   >= 2.0.1    && < 2.1,                  crypton-x509-system   >= 1.6.7    && < 1.7 @@ -716,6 +719,7 @@                    Text.Pandoc.Readers.Org.Shared,                    Text.Pandoc.Readers.Metadata,                    Text.Pandoc.Readers.Roff,+                   Text.Pandoc.Writers.Docx.OpenXML,                    Text.Pandoc.Writers.Docx.StyleMap,                    Text.Pandoc.Writers.Docx.Table,                    Text.Pandoc.Writers.Docx.Types,@@ -737,6 +741,7 @@                    Text.Pandoc.Writers.Blaze,                    Text.Pandoc.Writers.Powerpoint.Presentation,                    Text.Pandoc.Writers.Powerpoint.Output,+                   Text.Pandoc.Char,                    Text.Pandoc.TeX,                    Text.Pandoc.URI,                    Text.Pandoc.CSS,@@ -774,10 +779,10 @@                   tasty             >= 0.11    && < 1.6,                   tasty-golden      >= 2.3     && < 2.4,                   tasty-hunit       >= 0.9     && < 0.11,-                  tasty-quickcheck  >= 0.8     && < 0.11,+                  tasty-quickcheck  >= 0.8     && < 0.12,                   text              >= 1.1.1.0 && < 2.2,                   temporary         >= 1.1     && < 1.4,-                  time              >= 1.5     && < 1.14,+                  time              >= 1.5     && < 1.15,                   xml               >= 1.3.12  && < 1.4,                   zip-archive       >= 0.4.3   && < 0.5   other-modules:  Tests.Old
+ src/Text/Pandoc/Char.hs view
@@ -0,0 +1,59 @@+{- |+   Module      : Text.Pandoc.Char+   Copyright   : Copyright (C) 2024 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++Character functions not defined in Data.Char.+-}+module Text.Pandoc.Char ( isCJK )+where++-- | Returns True if character is CJK. Matches anything in:+--+-- * CJK Unified Ideographs Basic Block: U+4E00 - U+9FFF+-- * CJK Unified Ideographs Extension A: U+3400 - U+4DBF+-- * CJK Unified Ideographs Extension B: U+20000 - U+2A6DF+-- * CJK Unified Ideographs Extension C: U+2A700 - U+2B73F+-- * CJK Unified Ideographs Extension D: U+2B740 - U+2B81F+-- * CJK Compatibility Ideographs: U+F900 - U+FAFF+-- * CJK Compatibility Ideographs Supplement: U+2F800 - U+2FA1F+isCJK :: Char -> Bool+isCJK c =+  c >= '\x4e00' &&+  (    (c >= '\x2e80' && c <= '\x2eff') -- CJK Radicals Supplement+    || (c >= '\x2f00' && c <= '\x2fdf') -- Kangxi Radicals+    || (c >= '\x2ff0' && c <= '\x2fff') -- Ideographic Description Characters+    || (c >= '\x3000' && c <= '\x303f') -- JK Symbols and Punctuation+    || (c >= '\x3040' && c <= '\x309f') -- Hiragana+    || (c >= '\x30a0' && c <= '\x30ff') -- Katakana+    || (c >= '\x3100' && c <= '\x312f') -- Bopomofo+    || (c >= '\x3130' && c <= '\x318f') -- Kanbun+    || (c >= '\x3190' && c <= '\x319f') -- Kanbun+    || (c >= '\x31c0' && c <= '\x31ef') -- CJK Strokes+    || (c >= '\x31f0' && c <= '\x31ff') -- Katakana Phonetic Extensions+    || (c >= '\x3200' && c <= '\x32ff') -- Enclosed CJK Letters & Months+    || (c >= '\x3300' && c <= '\x33ff') -- CJK Compatibility+    || (c >= '\x3400' && c <= '\x4dbf') -- CJK Unified Ideographs Extension A+    || (c >= '\x4e00' && c <= '\x9fff') -- CJK Unified Ideographs+    || (c >= '\xa000' && c <= '\xa48f') -- Yi Syllables+    || (c >= '\xa490' && c <= '\xa4cf') -- Yi Radicals+    || (c >= '\xf900' && c <= '\xfaff') -- CJK Compatibility Ideographs+    || (c >= '\xfe10' && c <= '\xfe1f') -- Vertical forms+    || (c >= '\xfe30' && c <= '\xfe4f') -- CJK Compatibility Forms+    || (c >= '\xFE50' && c <= '\xFE6F') -- Small Form Variants+    || (c >= '\xFF00' && c <= '\xFFEE') -- Halfwidth and Fullwidth Forms+    || (c >= '\x1B000' && c <= '\x1B0FF') -- Kana Supplement+    || (c >= '\x1B100' && c <= '\x1B12F') -- Kana Extended-A+    || (c >= '\x1B130' && c <= '\x1B16F') -- Small Kana Extension+    || (c >= '\x20000' && c <= '\x2A6DF') -- CJK Unified Ideographs Extension B+    || (c >= '\x2A700' && c <= '\x2B73F') -- CJK Unified Ideographs Extension C+    || (c >= '\x2B740' && c <= '\x2B81F') -- CJK Unified Ideographs Extension D+    || (c >= '\x2B820' && c <= '\x2CEAF') -- CJK Unified Ideographs Extension E+    || (c >= '\x2CEB0' && c <= '\x2EBEF') -- CJK Unified Ideographs Extension F+    || (c >= '\x2F800' && c <= '\x2FA1F') -- CJK Compatibility Ideographs Supp+    || (c >= '\x30000' && c <= '\x3134F') -- CJK Unified Ideographs Exten+  )
src/Text/Pandoc/Class/PandocMonad.hs view
@@ -467,6 +467,11 @@               return $ Image attr lab (src, tit))           (\e ->               case e of+                PandocIOError text err -> do+                  report $ CouldNotFetchResource text . T.pack $+                            (show err ++ "\nReplacing image with description.")+                  -- emit alt text+                  return $ replacementSpan attr src tit lab                 PandocResourceNotFound _ -> do                   report $ CouldNotFetchResource src                             "replacing image with description"
src/Text/Pandoc/ImageSize.hs view
@@ -52,7 +52,6 @@ import Control.Applicative import qualified Data.Attoparsec.ByteString.Char8 as A import qualified Codec.Picture.Metadata as Metadata-import qualified Codec.Picture.Metadata.Exif as Exif import Codec.Picture (decodeImageWithMetadata)  -- quick and dirty functions to get image sizes@@ -315,17 +314,9 @@     Left e -> Left (T.pack e)     Right (_, meta) -> do       pxx <- maybe (Left "Could not determine width") Right $-                   -- first look for exif image width, then width-                   (Metadata.lookup-                     (Metadata.Exif (Exif.TagUnknown 0xA002)) meta >>=-                       exifDataToWord) <|>                    Metadata.lookup Metadata.Width meta       pxy <- maybe (Left "Could not determine height") Right $-                  -- first look for exif image height, then height-                  (Metadata.lookup-                     (Metadata.Exif (Exif.TagUnknown 0xA003)) meta >>=-                       exifDataToWord) <|>-                  Metadata.lookup Metadata.Height meta+                   Metadata.lookup Metadata.Height meta       dpix <- maybe (Right 72) Right $ Metadata.lookup Metadata.DpiX meta       dpiy <- maybe (Right 72) Right $ Metadata.lookup Metadata.DpiY meta       return $ ImageSize@@ -333,11 +324,6 @@                 , pxY = fromIntegral pxy                 , dpiX = fromIntegral dpix                 , dpiY = fromIntegral dpiy }- where-  exifDataToWord (Exif.ExifLong x) = Just $ fromIntegral x-  exifDataToWord (Exif.ExifShort x) = Just $ fromIntegral x-  exifDataToWord _ = Nothing-  svgSize :: WriterOptions -> ByteString -> Maybe ImageSize svgSize opts img = do
src/Text/Pandoc/Readers/CSV.hs view
@@ -25,6 +25,7 @@ import Text.Pandoc.Options (ReaderOptions) import Control.Monad.Except (throwError) import Data.Text (Text)+import Data.List (intersperse) import Text.Pandoc.Parsing (fromParsecError)  readCSV :: (PandocMonad m, ToSources a)@@ -60,7 +61,8 @@                                              (TableFoot nullAttr [])        where capt = B.emptyCaption              numcols = length r-             toplain = B.simpleCell . B.plain . B.text . T.strip+             toplain = B.simpleCell . B.plain . mconcat .+                       intersperse B.linebreak . map B.text . T.lines              toRow = Row nullAttr . map toplain              toHeaderRow l = [toRow l | not (null l)]              hdrs = toHeaderRow r
src/Text/Pandoc/Readers/Docx.hs view
@@ -78,7 +78,7 @@ import Data.Char (isSpace) import qualified Data.Map as M import qualified Data.Text as T-import Data.Maybe (catMaybes, isJust, fromMaybe, mapMaybe)+import Data.Maybe (isJust, fromMaybe, mapMaybe) import Data.Sequence (ViewL (..), viewl) import qualified Data.Sequence as Seq import qualified Data.Set as Set@@ -132,7 +132,6 @@                      -- restarting                      , docxListState :: M.Map (T.Text, T.Text) Integer                      , docxPrevPara  :: Inlines-                     , docxTableCaptions :: [Blocks]                      , docxReferences :: M.Map ItemId (Reference Inlines)                      } @@ -145,7 +144,6 @@                , docxDropCap   = mempty                , docxListState = M.empty                , docxPrevPara  = mempty-               , docxTableCaptions = []                , docxReferences = mempty                } @@ -385,22 +383,22 @@  parPartToInlines' :: PandocMonad m => ParPart -> DocxContext m Inlines parPartToInlines' (PlainRun r) = runToInlines r-parPartToInlines' (ChangedRuns (TrackedChange Insertion (ChangeInfo _ author date)) runs) = do+parPartToInlines' (ChangedRuns (TrackedChange Insertion (ChangeInfo _ author date)) pparts) = do   opts <- asks docxOptions   case readerTrackChanges opts of-    AcceptChanges -> smushInlines <$> mapM runToInlines runs+    AcceptChanges -> smushInlines <$> mapM parPartToInlines pparts     RejectChanges -> return mempty     AllChanges    -> do-      ils <- smushInlines <$> mapM runToInlines runs+      ils <- smushInlines <$> mapM parPartToInlines pparts       let attr = ("", ["insertion"], addAuthorAndDate author date)       return $ spanWith attr ils-parPartToInlines' (ChangedRuns (TrackedChange Deletion (ChangeInfo _ author date)) runs) = do+parPartToInlines' (ChangedRuns (TrackedChange Deletion (ChangeInfo _ author date)) pparts) = do   opts <- asks docxOptions   case readerTrackChanges opts of     AcceptChanges -> return mempty-    RejectChanges -> smushInlines <$> mapM runToInlines runs+    RejectChanges -> smushInlines <$> mapM parPartToInlines pparts     AllChanges    -> do-      ils <- smushInlines <$> mapM runToInlines runs+      ils <- smushInlines <$> mapM parPartToInlines pparts       let attr = ("", ["deletion"], addAuthorAndDate author date)       return $ spanWith attr ils parPartToInlines' (CommentStart cmtId author date bodyParts) = do@@ -590,10 +588,11 @@ singleParaToPlain blks = blks  cellToCell :: PandocMonad m => RowSpan -> Docx.Cell -> DocxContext m Pandoc.Cell-cellToCell rowSpan (Docx.Cell gridSpan _ bps) = do+cellToCell rowSpan (Docx.Cell align gridSpan _ bps) = do   blks <- smushBlocks <$> mapM bodyPartToBlocks bps   let blks' = singleParaToPlain $ fromList $ blocksToDefinitions $ blocksToBullets $ toList blks-  return (cell AlignDefault rowSpan (ColSpan (fromIntegral gridSpan)) blks')+  return (cell (convertAlign align)+          rowSpan (ColSpan (fromIntegral gridSpan)) blks')  rowsToRows :: PandocMonad m => [Docx.Row] -> DocxContext m [Pandoc.Row] rowsToRows rows = do@@ -613,7 +612,7 @@       | otherwise         = ((headerRows, r : bodyRows), False) -    isContinuationCell (Docx.Cell _ vm _) = vm == Docx.Continue+    isContinuationCell (Docx.Cell _ _ vm _) = vm == Docx.Continue   -- like trimInlines, but also take out linebreaks@@ -663,11 +662,6 @@   where go c | isSpace c = '-'              | otherwise = c -bodyPartToTableCaption :: PandocMonad m => BodyPart -> DocxContext m (Maybe Blocks)-bodyPartToTableCaption (TblCaption pPr parparts) =-  Just <$> bodyPartToBlocks (Paragraph pPr parparts)-bodyPartToTableCaption _ = pure Nothing- bodyPartToBlocks :: PandocMonad m => BodyPart -> DocxContext m Blocks bodyPartToBlocks (Paragraph pPr parparts)   | Just True <- pBidi pPr = do@@ -766,32 +760,39 @@   let pPr' = pPr {pStyle = constructBogusParStyleData "list-paragraph": pStyle pPr}   in     bodyPartToBlocks $ Paragraph pPr' parparts-bodyPartToBlocks (TblCaption _ _) =-  return mempty+bodyPartToBlocks (Captioned parstyle parparts bpart) = do+  bs <- bodyPartToBlocks bpart+  captContents <- bodyPartToBlocks (Paragraph parstyle parparts)+  let capt = Caption Nothing (toList captContents)+  case toList bs of+    [Table attr _cap colspecs thead tbodies tfoot]+      -> pure $ singleton $ Table attr capt colspecs thead tbodies tfoot+    [Figure attr _cap blks]+      -> pure $ singleton $ Figure attr capt blks+    [Para im@[Image{}]]+      -> pure $ singleton $ Figure nullAttr capt [Plain im]+    _ -> pure captContents bodyPartToBlocks (Tbl _ _ _ []) =   return mempty bodyPartToBlocks (Tbl cap grid look parts) = do-  captions <- gets docxTableCaptions-  fullCaption <- case captions of-    c : cs -> do-      modify (\s -> s { docxTableCaptions = cs })-      return c-    [] -> return $ if T.null cap then mempty else plain (text cap)+  let fullCaption = if T.null cap then mempty else plain (text cap)   let shortCaption = if T.null cap then Nothing else Just (toList (text cap))       cap' = caption shortCaption fullCaption       (hdr, rows) = splitHeaderRows (firstRowFormatting look) parts    let width = maybe 0 maximum $ nonEmpty $ map rowLength parts       rowLength :: Docx.Row -> Int-      rowLength (Docx.Row _ c) = sum (fmap (\(Docx.Cell gridSpan _ _) -> fromIntegral gridSpan) c)+      rowLength (Docx.Row _ c) = sum (fmap (\(Docx.Cell _ gridSpan _ _) -> fromIntegral gridSpan) c)    headerCells <- rowsToRows hdr   bodyCells <- rowsToRows rows -      -- Horizontal column alignment goes to the default at the moment. Getting-      -- it might be difficult, since there doesn't seem to be a column entity-      -- in docx.-  let alignments = replicate width AlignDefault+      -- Horizontal column alignment is taken from the first row's cells.+  let getAlignment (Docx.Cell al colspan _ _) = replicate (fromIntegral colspan)+                   $ convertAlign al+      alignments = case rows of+                     [] -> replicate width Pandoc.AlignDefault+                     Docx.Row _ cs : _ -> concatMap getAlignment cs       totalWidth = sum grid       widths = (\w -> ColWidth (fromInteger w / fromInteger totalWidth)) <$> grid @@ -800,6 +801,7 @@                  (TableHead nullAttr headerCells)                  [TableBody nullAttr 0 [] bodyCells]                  (TableFoot nullAttr [])+bodyPartToBlocks HRule = pure Pandoc.horizontalRule  -- replace targets with generated anchors. rewriteLink' :: PandocMonad m => Inline -> DocxContext m Inline@@ -836,11 +838,9 @@ bodyToOutput (Body bps) = do   let (metabps, blkbps) = sepBodyParts bps   meta <- bodyPartsToMeta metabps-  captions <- catMaybes <$> mapM bodyPartToTableCaption blkbps   let isNumberedPara (Paragraph pPr _) = numbered pPr       isNumberedPara _                 = False   modify (\s -> s { docxNumberedHeadings = any isNumberedPara blkbps })-  modify (\s -> s { docxTableCaptions = captions })   blks <- smushBlocks <$> mapM bodyPartToBlocks blkbps   blks' <- rewriteLinks $ blocksToDefinitions $ blocksToBullets $ toList blks   blks'' <- removeOrphanAnchors blks'@@ -861,3 +861,10 @@ addAuthorAndDate :: T.Text -> Maybe T.Text -> [(T.Text, T.Text)] addAuthorAndDate author mdate =   ("author", author) : maybe [] (\date -> [("date", date)]) mdate++convertAlign :: Docx.Align -> Pandoc.Alignment+convertAlign al = case al of+                       Docx.AlignDefault -> Pandoc.AlignDefault+                       Docx.AlignLeft -> Pandoc.AlignLeft+                       Docx.AlignCenter -> Pandoc.AlignCenter+                       Docx.AlignRight -> Pandoc.AlignRight
src/Text/Pandoc/Readers/Docx/Lists.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {- |    Module      : Text.Pandoc.Readers.Docx.Lists@@ -18,10 +19,11 @@                                       ) where  import Data.List+import Data.Char (isDigit) import Data.Maybe import Data.String (fromString) import qualified Data.Text as T-import Text.Pandoc.Generic (bottomUp)+import Text.Pandoc.Walk (walk) import Text.Pandoc.JSON import Text.Pandoc.Readers.Docx.Parse (ParaStyleName) import Text.Pandoc.Shared (trim, safeRead)@@ -58,9 +60,9 @@                 ("decimal", Decimal)]  listDelimMap :: [(T.Text, ListNumberDelim)]-listDelimMap = [("%1)", OneParen),-                ("(%1)", TwoParens),-                ("%1.", Period)]+listDelimMap = [("%)", OneParen),+                ("(%)", TwoParens),+                ("%.", Period)]  getListType :: Block -> Maybe ListType getListType b@(Div (_, _, kvs) _) | isListItem b =@@ -72,7 +74,7 @@    case frmt of      Just "bullet" -> Just Itemized      Just f        ->-       case txt of+       case T.filter (not . isDigit) <$> txt of          Just t -> Just $ Enumerated (                   fromMaybe 1 (start >>= safeRead) :: Int,                   fromMaybe DefaultStyle (lookup f listStyleMap),@@ -122,25 +124,48 @@  flatToBullets' :: Integer -> [Block] -> [Block] flatToBullets' _ [] = []-flatToBullets' num xs@(b : elems)-  | getLevelN b == num = b : flatToBullets' num elems-  | otherwise =-    let bNumId = getNumIdN b-        bLevel = getLevelN b-        (children, remaining) =-          span-          (\b' ->-            getLevelN b' > bLevel ||-             (getLevelN b' == bLevel && getNumIdN b' == bNumId))-          xs-    in-     case getListType b of-       Just (Enumerated attr) ->-         OrderedList attr (separateBlocks $ flatToBullets' bLevel children) :-         flatToBullets' num remaining-       _ ->-         BulletList (separateBlocks $ flatToBullets' bLevel children) :-         flatToBullets' num remaining+flatToBullets' num xs@(b : elems) =+  if getLevelN b == num+     then (case bCheckmark of+             Just checked -> addCheckmark checked b+             Nothing -> b) : flatToBullets' num elems+     else case getListType b of+            Just (Enumerated attr) ->+              OrderedList attr (separateBlocks $ flatToBullets' bLevel children) :+              flatToBullets' num remaining+            _ ->+              BulletList (separateBlocks $ flatToBullets' bLevel children) :+              flatToBullets' num remaining+ where+  bNumId = getNumIdN b+  bLevel = getLevelN b+  isCheckmark (Just "\9744") = Just False+  isCheckmark (Just "\9746") = Just True+  isCheckmark _ = Nothing+  bCheckmark =+    case getListType b of+      Just Itemized -> isCheckmark (getText b)+      _ -> Nothing+  addCheckmark checked (Div attrs [Para ils]) =+    Div attrs [Para (Str (if checked then "\9746" else "\9744") : Space : ils)]+  addCheckmark checked (Div attrs [Plain ils]) =+    Div attrs [Plain (Str (if checked then "\9746" else "\9744") : Space : ils)]+  addCheckmark _ x = x+  (children, remaining) =+    span+    (\b' ->+      getLevelN b' > bLevel ||+       (getLevelN b' == bLevel &&+          (getNumIdN b' == bNumId ||+            (case bCheckmark of+               Just _ ->+                 case getText b' of+                   Just "" -> True+                   Just " " -> True+                   Just x -> isJust (isCheckmark (Just x))+                   Nothing -> False+               Nothing -> False))))+    xs  flatToBullets :: [Block] -> [Block] flatToBullets elems = flatToBullets' (-1) elems@@ -153,7 +178,7 @@ blocksToBullets :: [Block] -> [Block] blocksToBullets blks =   map singleItemHeaderToHeader $-  bottomUp removeListDivs $ flatToBullets (handleListParagraphs blks)+  walk removeListDivs $ flatToBullets (handleListParagraphs blks)  plainParaInlines :: Block -> [Inline] plainParaInlines (Plain ils) = ils
src/Text/Pandoc/Readers/Docx/Parse.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE ViewPatterns      #-} {-# LANGUAGE TupleSections     #-} {-# LANGUAGE LambdaCase        #-} {-# LANGUAGE OverloadedStrings #-}@@ -31,11 +30,13 @@                                       , RunStyle(..)                                       , VertAlign(..)                                       , ParIndentation(..)+                                      , Justification(..)                                       , ParagraphStyle(..)                                       , ParStyle                                       , CharStyle(cStyleData)                                       , Row(..)                                       , TblHeader(..)+                                      , Align(..)                                       , Cell(..)                                       , VMerge(..)                                       , TrackedChange(..)@@ -255,29 +256,37 @@ data TrackedChange = TrackedChange ChangeType ChangeInfo                    deriving Show -data ParagraphStyle = ParagraphStyle { pStyle      :: [ParStyle]-                                     , indentation :: Maybe ParIndentation-                                     , numbered    :: Bool-                                     , dropCap     :: Bool-                                     , pChange     :: Maybe TrackedChange-                                     , pBidi       :: Maybe Bool+data Justification = JustifyBoth | JustifyLeft | JustifyRight | JustifyCenter+  deriving (Show, Eq)++data ParagraphStyle = ParagraphStyle { pStyle        :: [ParStyle]+                                     , indentation   :: Maybe ParIndentation+                                     , justification :: Maybe Justification+                                     , numbered      :: Bool+                                     , dropCap       :: Bool+                                     , pChange       :: Maybe TrackedChange+                                     , pBidi         :: Maybe Bool+                                     , pKeepNext     :: Bool                                      }                       deriving Show  defaultParagraphStyle :: ParagraphStyle defaultParagraphStyle = ParagraphStyle { pStyle = []                                        , indentation = Nothing-                                       , numbered    = False-                                       , dropCap     = False-                                       , pChange     = Nothing-                                       , pBidi       = Just False+                                       , justification = Nothing+                                       , numbered = False+                                       , dropCap = False+                                       , pChange = Nothing+                                       , pBidi = Just False+                                       , pKeepNext = False                                        }   data BodyPart = Paragraph ParagraphStyle [ParPart]               | ListItem ParagraphStyle T.Text T.Text (Maybe Level) [ParPart]               | Tbl T.Text TblGrid TblLook [Row]-              | TblCaption ParagraphStyle [ParPart]+              | Captioned ParagraphStyle [ParPart] BodyPart+              | HRule               deriving Show  type TblGrid = [Integer]@@ -292,7 +301,10 @@  data TblHeader = HasTblHeader | NoTblHeader deriving (Show, Eq) -data Cell = Cell GridSpan VMerge [BodyPart]+data Align = AlignDefault | AlignLeft | AlignRight | AlignCenter+  deriving (Show, Eq)++data Cell = Cell Align GridSpan VMerge [BodyPart]             deriving Show  type GridSpan = Integer@@ -305,7 +317,7 @@  rowsToRowspans :: [Row] -> [[(Int, Cell)]] rowsToRowspans rows = let-  removeMergedCells = fmap (filter (\(_, Cell _ vmerge _) -> vmerge == Restart))+  removeMergedCells = fmap (filter (\(_, Cell _ _ vmerge _) -> vmerge == Restart))   in removeMergedCells (foldr f [] rows)   where     f :: Row -> [[(Int, Cell)]] -> [[(Int, Cell)]]@@ -321,9 +333,9 @@     g cells columnsLeftBelow (Just rowBelow) =         case cells of           [] -> []-          thisCell@(Cell thisGridSpan _ _) : restOfRow -> case rowBelow of+          thisCell@(Cell _ thisGridSpan _ _) : restOfRow -> case rowBelow of             [] -> map (1,) cells-            (spanSoFarBelow, Cell gridSpanBelow vmerge _) : _ ->+            (spanSoFarBelow, Cell _ gridSpanBelow vmerge _) : _ ->               let spanSoFar = case vmerge of                     Restart -> 1                     Continue -> 1 + spanSoFarBelow@@ -333,7 +345,7 @@      dropColumns :: Integer -> [(a, Cell)] -> (Integer, [(a, Cell)])     dropColumns n [] = (n, [])-    dropColumns n cells@((_, Cell gridSpan _ _) : otherCells) =+    dropColumns n cells@((_, Cell _ gridSpan _ _) : otherCells) =       if n < gridSpan       then (gridSpan - n, cells)       else dropColumns (n - gridSpan) otherCells@@ -358,7 +370,7 @@ type Extent = Maybe (Double, Double)  data ParPart = PlainRun Run-             | ChangedRuns TrackedChange [Run]+             | ChangedRuns TrackedChange [ParPart]              | CommentStart CommentId Author (Maybe CommentDate) [BodyPart]              | CommentEnd CommentId              | BookMark BookMarkId Anchor@@ -461,7 +473,7 @@  elemToBody :: NameSpaces -> Element -> D Body elemToBody ns element | isElem ns "w" "body" element =-  fmap Body (mapD (elemToBodyPart ns) (elChildren element))+  Body . addCaptioned <$> mapD (elemToBodyPart ns) (elChildren element) elemToBody _ _ = throwError WrongElem  archiveToStyles :: Archive -> (CharStyleMap, ParStyleMap)@@ -718,7 +730,16 @@                          "restart" -> Just Restart                          _ -> Nothing     cellContents <- mapD (elemToBodyPart ns) (elChildren element)-    return $ Cell (fromMaybe 1 gridSpan) vMerge cellContents+    let align = case cellContents of -- take alignment from first paragraph+                  Paragraph pstyle _ : _ ->+                    case justification pstyle of+                      Just JustifyBoth -> AlignLeft+                      Just JustifyLeft -> AlignLeft+                      Just JustifyRight -> AlignRight+                      Just JustifyCenter -> AlignCenter+                      Nothing -> AlignDefault+                  _ -> AlignDefault+    return $ Cell align (fromMaybe 1 gridSpan) vMerge cellContents elemToCell _ _ = throwError WrongElem  testBitMask :: Text -> Int -> Bool@@ -741,6 +762,24 @@ pStyleIndentation :: ParagraphStyle -> Maybe ParIndentation pStyleIndentation style = (getParStyleField indent . pStyle) style +addCaptioned :: [BodyPart] -> [BodyPart]+addCaptioned [] = []+addCaptioned (Paragraph parstyle parparts : x : xs)+  | hasCaptionStyle parstyle+  , isCaptionable x+    = Captioned parstyle parparts x : addCaptioned xs+addCaptioned (x : Paragraph parstyle parparts : xs)+  | hasCaptionStyle parstyle+  , not (pKeepNext parstyle)+  , isCaptionable x+    = Captioned parstyle parparts x : addCaptioned xs+addCaptioned (x:xs) = x : addCaptioned xs++isCaptionable :: BodyPart -> Bool+isCaptionable (Paragraph _ [Drawing{}]) = True+isCaptionable (Tbl{}) = True+isCaptionable _ = False+ elemToBodyPart :: NameSpaces -> Element -> D BodyPart elemToBodyPart ns element   | isElem ns "m" "oMathPara" element = do@@ -758,43 +797,46 @@     parparts <- mconcat <$> mapD (elemToParPart ns) (elChildren element)     case pHeading parstyle of       Nothing -> mkListItem parstyle numId lvl parparts-      Just _  -> do-        return $ Paragraph parstyle parparts+      Just _  -> return $ Paragraph parstyle parparts elemToBodyPart ns element+  | isElem ns "w" "p" element+  , [Elem ppr] <- elContent element+  , isElem ns "w" "pPr" ppr+  , [Elem pbdr] <- elContent ppr+  , isElem ns "w" "pBdr" pbdr+    = return HRule+      -- for this style of horizontal rule, see+      -- https://support.microsoft.com/en-us/office/insert-a-horizontal-line-9bf172f6-5908-4791-9bb9-2c952197b1a9+elemToBodyPart ns element -- pandoc-style horizontal rule+  | isElem ns "w" "p" element+  , [Elem r] <- elContent element+  , isElem ns "w" "r" r+  , [Elem pict] <- elContent r+  , isElem ns "w" "pict" pict+  , [Elem rect] <- elContent pict+  , isElem ns "v" "rect" rect+    = return HRule+elemToBodyPart ns element   | isElem ns "w" "p" element = do       parstyle <- elemToParagraphStyle ns element                   <$> asks envParStyles                   <*> asks envNumbering -      let hasCaptionStyle =-            any ((== "caption") . pStyleName) (pStyle parstyle)--      let isTableNumberElt el@(Element name attribs _ _) =-           (qName name == "fldSimple" &&-             case lookupAttrBy ((== "instr") . qName) attribs of-               Nothing -> False-               Just instr -> "Table" `elem` T.words instr) ||-           (qName name == "instrText" && "Table" `elem` T.words (strContent el))--      let isTable = hasCaptionStyle &&-                      isJust (filterChild isTableNumberElt element)--      let stripOffLabel = dropWhile (not . isTableNumberElt)+      let children =+            (if hasCaptionStyle parstyle+                then stripCaptionLabel+                else id) (elChildren element) -      let children = (if isTable-                          then stripOffLabel-                          else id) $ elChildren element       parparts' <- mconcat <$> mapD (elemToParPart ns) children       fldCharState <- gets stateFldCharState       modify $ \st -> st {stateFldCharState = emptyFldCharContents fldCharState}       -- Word uses list enumeration for numbered headings, so we only       -- want to infer a list from the styles if it is NOT a heading.-      let parparts = parparts' ++ (openFldCharsToParParts fldCharState)+      let parparts = parparts' ++ openFldCharsToParParts fldCharState       case pHeading parstyle of         Nothing | Just (numId, lvl) <- pNumInfo parstyle -> do                     mkListItem parstyle numId lvl parparts-        _ -> return $ (if hasCaptionStyle then TblCaption else Paragraph)-                      parstyle parparts+        _ -> return $ Paragraph parstyle parparts  elemToBodyPart ns element   | isElem ns "w" "tbl" element = do@@ -1009,7 +1051,7 @@     return $ map PlainRun runs elemToParPart' ns element   | Just change <- getTrackedChange ns element = do-      runs <- mconcat <$> mapD (elemToRun ns) (elChildren element)+      runs <- mconcat <$> mapD (elemToParPart' ns) (elChildren element)       return [ChangedRuns change runs] elemToParPart' ns element   | isElem ns "w" "bookmarkStart" element@@ -1196,6 +1238,14 @@       , numbered = case getNumInfo ns element of           Just (numId, lvl) -> isJust $ lookupLevel numId lvl numbering           Nothing -> isJust $ getParStyleField numInfo pStyle'+      , justification =+          case findChildByName ns "w" "jc" pPr >>= findAttrByName ns "w" "val" of+            Nothing -> Nothing+            Just "both" -> Just JustifyBoth+            Just "center" -> Just JustifyCenter+            Just "left" -> Just JustifyLeft+            Just "right" -> Just JustifyRight+            _ -> Nothing       , indentation =           getIndentation ns element       , dropCap =@@ -1214,6 +1264,7 @@                                   ) >>=                       getTrackedChange ns       , pBidi = checkOnOff ns pPr (elemName ns "w" "bidi")+      , pKeepNext = isJust $ findChildByName ns "w" "keepNext" pPr       }   | otherwise = defaultParagraphStyle @@ -1290,3 +1341,27 @@   filterElementName (\(QName tag _ _) -> tag == "svgBlip") el `mplus` pure blip  where   a_ns = "http://schemas.openxmlformats.org/drawingml/2006/main"++hasCaptionStyle :: ParagraphStyle -> Bool+hasCaptionStyle parstyle = any (isCaptionStyleName . pStyleName) (pStyle parstyle)+ where -- note that these are case insensitive:+   isCaptionStyleName "caption" = True+   isCaptionStyleName "table caption" = True+   isCaptionStyleName "image caption" = True+   isCaptionStyleName _ = False++stripCaptionLabel :: [Element] -> [Element]+stripCaptionLabel els =+  if any isNumberElt els+     then dropWhile (not . isNumberElt) els+     else els+  where+    isNumberElt el@(Element name attribs _ _) =+       (qName name == "fldSimple" &&+             case lookupAttrBy ((== "instr") . qName) attribs of+               Nothing -> False+               Just instr -> "Table" `elem` T.words instr ||+                             "Figure" `elem` T.words instr) ||+       (qName name == "instrText" &&+          let ws = T.words (strContent el)+          in  ("Table" `elem` ws || "Figure" `elem` ws))
src/Text/Pandoc/Readers/HTML.hs view
@@ -328,17 +328,20 @@ pBulletList :: PandocMonad m => TagParser m Blocks pBulletList = try $ do   pSatisfy (matchTagOpen "ul" [])-  let nonItem = pSatisfy (\t ->-                  not (tagOpen (`elem` ["li","ol","ul","dl"]) (const True) t) &&-                  not (matchTagClose "ul" t))   -- note: if they have an <ol> or <ul> not in scope of a <li>,   -- treat it as a list item, though it's not valid xhtml...-  skipMany nonItem-  items <- manyTill (pListItem nonItem) (pCloses "ul")-  return $ B.bulletList $ map (fixPlains True) items+  skipMany pBlank+  orphans <- many (do notFollowedBy (pSatisfy (matchTagOpen "li" []))+                      notFollowedBy (pSatisfy isTagClose)+                      block) -- e.g. <ul>, see #9187+  items <- manyTill pListItem (pCloses "ul")+  let items' = case orphans of+                 [] -> items+                 xs -> mconcat xs : items+  return $ B.bulletList $ map (fixPlains True) items' -pListItem :: PandocMonad m => TagParser m a -> TagParser m Blocks-pListItem nonItem = setInListItem $ do+pListItem :: PandocMonad m => TagParser m Blocks+pListItem = setInListItem $ do   TagOpen _ attr' <- lookAhead $ pSatisfy (matchTagOpen "li" [])   let attr = toStringAttr attr'   let addId ident bs = case B.toList bs of@@ -346,10 +349,11 @@                                 [Span (ident, [], []) ils] : xs)                            _ -> B.divWith (ident, [], []) bs   item <- pInTags "li" block-  skipMany nonItem+  skipMany pBlank   orphans <- many (do notFollowedBy (pSatisfy (matchTagOpen "li" []))                       notFollowedBy (pSatisfy isTagClose)                       block) -- e.g. <ul>, see #9187+  skipMany pBlank   return $ maybe id addId (lookup "id" attr) $ item <> mconcat orphans  pCheckbox :: PandocMonad m => TagParser m Inlines@@ -391,20 +395,23 @@         where           pickListStyle = pickStyleAttrProps ["list-style-type", "list-style"] -  let nonItem = pSatisfy (\t ->-                  not (tagOpen (`elem` ["li","ol","ul","dl"]) (const True) t) &&-                  not (matchTagClose "ol" t))   -- note: if they have an <ol> or <ul> not in scope of a <li>,   -- treat it as a list item, though it's not valid xhtml...-  skipMany nonItem+  skipMany pBlank+  orphans <- many (do notFollowedBy (pSatisfy (matchTagOpen "li" []))+                      notFollowedBy (pSatisfy isTagClose)+                      block) -- e.g. <ul>, see #9187   if isNoteList      then do        _ <- manyTill (eFootnote <|> pBlank) (pCloses "ol")        return mempty      else do-       items <- manyTill (pListItem nonItem) (pCloses "ol")+       items <- manyTill pListItem (pCloses "ol")+       let items' = case orphans of+                      [] -> items+                      xs -> mconcat xs : items        return $ B.orderedListWith (start, style, DefaultDelim) $-                map (fixPlains True) items+                map (fixPlains True) items'  pDefinitionList :: PandocMonad m => TagParser m Blocks pDefinitionList = try $ do
src/Text/Pandoc/Readers/LaTeX/Parsing.hs view
@@ -885,7 +885,12 @@   optional sp   ch  <- option False $ True <$ symbol '='   minus <- option "" $ "-" <$ symbol '-'-  Tok _ _ s1 <- satisfyTok isWordTok+  s1 <- option ""+        (do Tok _ _ s1 <- satisfyTok isWordTok+            guard (case T.uncons s1 of+                     Just (c,_) -> isDigit c+                     Nothing -> False)+            pure s1)   s2 <- option "" $ try $ do           symbol '.'           Tok _ _ t <-  satisfyTok isWordTok
src/Text/Pandoc/Readers/Markdown.hs view
@@ -1541,7 +1541,7 @@      '\145'  -> smart      '\8220' -> smart      '\147'  -> smart-     '-'     -> smart+     '-'     -> cite <|> smart      '.'     -> smart      '&'     -> return . B.singleton <$> charRef      ':'     -> emoji
src/Text/Pandoc/Readers/MediaWiki.hs view
@@ -38,6 +38,7 @@ import Text.Pandoc.Readers.HTML (htmlTag, isBlockTag, isCommentTag, toAttr) import Text.Pandoc.Shared (safeRead, stringify, stripTrailingNewlines,                            trim, splitTextBy, tshow, formatCode)+import Text.Pandoc.Char (isCJK) import Text.Pandoc.XML (fromEntities)  -- | Read mediawiki from an input string and return a Pandoc document.@@ -676,23 +677,6 @@        updateState $ \st -> st{ mwCategoryLinks = link : mwCategoryLinks st }        return mempty      else return link--isCJK :: Char -> Bool-isCJK c =-  (c >= '\x3400' && c <= '\x4DBF') ||-  (c >= '\x4E00' && c <= '\x9FFF') ||-  (c >= '\x20000' && c <= '\x2A6DF') ||-  (c >= '\x2A700' && c <= '\x2B73F') ||-  (c >= '\x2B740' && c <= '\x2B81F') ||-  (c >= '\x2B820' && c <= '\x2CEAF') ||-  (c >= '\x2CEB0' && c <= '\x2EBEF') ||-  (c >= '\x30000' && c <= '\x3134F') ||-  (c >= '\x31350' && c <= '\x323AF') ||-  (c >= '\xF900' && c <= '\xFAFF') ||-  (c >= '\x2F800' && c <= '\x2FA1F') ||-  (c >= '\x2F00' && c <= '\x2FDF') ||-  (c >= '\x2E80' && c <= '\x2EFF') ||-  (c >= '\x3000' && c <= '\x303F')  externalLink :: PandocMonad m => MWParser m Inlines externalLink = try $ do
src/Text/Pandoc/Readers/RST.hs view
@@ -15,10 +15,12 @@ -} module Text.Pandoc.Readers.RST ( readRST ) where import Control.Arrow (second)-import Control.Monad (forM_, guard, liftM, mplus, mzero, when)+import Control.Monad (forM_, guard, liftM, mplus, mzero, when, unless) import Control.Monad.Except (throwError) import Control.Monad.Identity (Identity (..))-import Data.Char (isHexDigit, isSpace, toUpper, isAlphaNum)+import Data.Char (isHexDigit, isSpace, toUpper, isAlphaNum, generalCategory,+                  GeneralCategory(OpenPunctuation, InitialQuote, FinalQuote,+                                  DashPunctuation, OtherSymbol)) import Data.List (deleteFirstsBy, elemIndex, nub, partition, sort, transpose) import qualified Data.Map as M import Data.Maybe (fromMaybe, maybeToList, isJust)@@ -748,6 +750,7 @@                           Just t  -> B.link (escapeURI $ trim t) ""                                      $ B.imageWith attr src "" alt                           Nothing -> B.imageWith attr src "" alt+        "bibliography" -> pure $ B.divWith ("refs",[],[]) mempty         "class" -> do             let attrs = (name, T.words (trim top), map (second trimr) fields)             --  directive content or the first immediately following element@@ -1302,8 +1305,7 @@  simpleTableSplitLine :: [Int] -> Text -> [Text] simpleTableSplitLine indices line =-  map trimr-  $ tail $ splitTextByIndices (init indices) line+  map trimr $ drop 1 $ splitTextByIndices (init indices) line  simpleTableHeader :: PandocMonad m                   => Bool  -- ^ Headerless table@@ -1391,17 +1393,24 @@   -- don't want to treat endline after hyphen or dash as a space   return $ B.str result -escapedChar :: Monad m => ParsecT Sources st m Inlines+escapedChar :: Monad m => RSTParser m Inlines escapedChar = do c <- escaped anyChar+                 unless (canPrecedeOpener c) $ updateLastStrPos                  return $ if c == ' ' || c == '\n' || c == '\r'                              -- '\ ' is null in RST                              then mempty                              else B.str $ T.singleton c +canPrecedeOpener :: Char -> Bool+canPrecedeOpener c =+  generalCategory c `elem`+   [OpenPunctuation, InitialQuote, FinalQuote, DashPunctuation, OtherSymbol]+ symbol :: Monad m => RSTParser m Inlines symbol = do-  result <- oneOf specialChars-  return $ B.str $ T.singleton result+  c <- oneOf specialChars+  unless (canPrecedeOpener c) $ updateLastStrPos+  return $ B.str $ T.singleton c  -- parses inline code, between codeStart and codeEnd code :: Monad m => RSTParser m Inlines@@ -1462,7 +1471,10 @@     "code" -> return $ B.codeWith attr contents     "span" -> return $ B.spanWith attr $ treatAsText contents     "raw" -> return $ B.rawInline (fromMaybe "" fmt) contents-    custom -> do+    custom+     | Just citeType <- T.stripPrefix "cite" custom+       -> cite citeType contents+     | otherwise -> do         customRoles <- stateRstCustomRoles <$> getState         case M.lookup custom customRoles of             Just (newRole, newFmt, newAttr) ->@@ -1482,6 +1494,40 @@      where headSpace t = fromMaybe t $ T.stripPrefix " " t            removeSpace (x:xs) = x : map headSpace xs            removeSpace []     = []++cite :: PandocMonad m => Text -> Text -> RSTParser m Inlines+cite citeType rawcite = do+  let citations =+        case map parseCite (T.splitOn "," rawcite) of+                (c:cs)+                  | citeType == ":t" || citeType == ":ct"+                     -> c{ citationMode = AuthorInText } : cs+                  | citeType == ":year" || citeType == ":yearpar"+                     -> c{ citationMode = SuppressAuthor } : cs+                cs -> cs+  pure $ B.cite citations (B.str rawcite)++parseCite :: Text -> Citation+parseCite t =+  let (_, pref, suff, ident) = T.foldl go (ParseStart, "", "", "") t+  in  Citation{citationId = ident+              ,citationPrefix = B.toList $ B.text pref+              ,citationSuffix = B.toList $ B.text suff+              ,citationMode = NormalCitation+              ,citationNoteNum = 0+              ,citationHash = 0}+ where+   go (ParseStart, p, s, i) '{' = (ParsePrefix, p, s, i)+   go (ParseStart, p, s, i) c = (ParseId, p, s, T.snoc i c)+   go (ParsePrefix, p, s, i) '}' = (ParseId, p, s, i)+   go (ParsePrefix, p, s, i) c = (ParsePrefix, T.snoc p c, s, i)+   go (ParseId, p, s, i) '{' = (ParseSuffix, p, s, i)+   go (ParseId, p, s, i) c = (ParseId, p, s, T.snoc i c)+   go (ParseSuffix, p, s, i) '}' = (ParseSuffix, p, s, i)+   go (ParseSuffix, p, s, i) c = (ParseSuffix, p, T.snoc s c, i)++data ParseCiteState = ParseStart | ParsePrefix | ParseSuffix | ParseId+  deriving (Show)  -- single words consisting of alphanumerics plus isolated (no two adjacent) -- internal hyphens, underscores, periods, colons and plus signs;
src/Text/Pandoc/Readers/Textile.hs view
@@ -685,9 +685,12 @@  -- | Any special symbol defined in wordBoundaries symbol :: PandocMonad m => TextileParser m Inlines-symbol = B.str . T.singleton <$> (notFollowedBy newline *>-                                  notFollowedBy rawHtmlBlock *>-                                  oneOf wordBoundaries)+symbol = do+  c <- notFollowedBy newline *>+         notFollowedBy rawHtmlBlock *>+         oneOf wordBoundaries+  updateLastStrPos+  pure $ B.str . T.singleton $ c  -- | Inline code code :: PandocMonad m => TextileParser m Inlines
src/Text/Pandoc/Readers/Typst.hs view
@@ -105,8 +105,10 @@           B.math . writeTeX <$> pMathMany (Seq.singleton res)     Elt name@(Identifier tname) pos fields -> do       labs <- sLabels <$> getState-      labelTarget <- (do VLabel t <- getField "target" fields-                         True <$ guard (t `elem` labs))+      labelTarget <- (do result <- getField "target" fields+                         case result of+                           VLabel t | t `elem` labs -> pure True+                           _ -> pure False)                   <|> pure False       if tname == "ref" && not labelTarget          then do@@ -537,7 +539,8 @@  pInlines :: PandocMonad m => P m B.Inlines pInlines =-  collapseAdjacentCites . mconcat <$> many pInline+  mappend <$> (collapseAdjacentCites . mconcat <$> many pInline)+          <*> ((B.softbreak <$ pParBreak) <|> pure mempty)  collapseAdjacentCites :: B.Inlines -> B.Inlines collapseAdjacentCites = B.fromList . foldr go [] . B.toList
src/Text/Pandoc/SelfContained.hs view
@@ -52,8 +52,11 @@ makeDataURI (mime, raw) =   if textual      then "data:" <> mime' <> "," <> T.pack (escapeURIString isOk (toString raw))-     else "data:" <> mime' <> ";base64," <> toText (encode raw)+     else "data:" <> mime' <> ";base64," <> toText (encode raw')   where textual = "text/" `T.isPrefixOf` mime+        raw' = if "+xml" `T.isSuffixOf` mime+                  then B.filter (/= '\r') raw  -- strip off CRs+                  else raw         mime' = if textual && T.any (== ';') mime                    then mime <> ";charset=utf-8"                    else mime  -- mime type already has charset@@ -145,7 +148,11 @@ convertTags (t@(TagOpen tagname as):ts)   | any (isSourceAttribute tagname) as      = do-       as' <- mapM processAttribute as+       let inlineSvgs = tagname == "img" &&+                        case T.words <$> lookup "class" as of+                          Nothing -> False+                          Just cs -> "inline-svg" `elem` cs+       as' <- mapM (processAttribute inlineSvgs) as        let attrs = addRole "img" $ addAriaLabel $ rights as'        let svgContents = lefts as'        rest <- convertTags ts@@ -200,13 +207,13 @@                       return $ TagOpen "svg" attrs'' :                                  map ensureUniqueId tags' ++ rest'                     _ -> return $ TagOpen tagname attrs : rest-  where processAttribute (x,y) =+  where processAttribute inlineSvgs (x,y) =            if isSourceAttribute tagname (x,y)               then do                 res <- getData (fromAttrib "type" t) y                 case res of                   AlreadyDataURI enc -> return $ Right (x, enc)-                  Fetched ("image/svg+xml", bs) -> do+                  Fetched ("image/svg+xml", bs) | inlineSvgs -> do                     -- we filter CR in the hash to ensure that Windows                     -- and non-Windows tests agree:                     let hash = T.pack $ take 20 $ showDigest $
src/Text/Pandoc/Shared.hs view
@@ -98,6 +98,7 @@ import Data.Sequence (ViewL (..), ViewR (..), viewl, viewr) import qualified Data.Set as Set import qualified Data.Text as T+import qualified Text.Emoji as Emoji import System.Directory import System.FilePath (isPathSeparator, splitDirectories) import qualified System.FilePath.Posix as Posix@@ -464,7 +465,7 @@ -- | Convert Pandoc inline list to plain text identifier. inlineListToIdentifier :: Extensions -> [Inline] -> T.Text inlineListToIdentifier exts =-  textToIdentifier exts . stringify . walk unEmojify+  textToIdentifier exts . stringify . unEmojify   where     unEmojify :: [Inline] -> [Inline]     unEmojify@@ -472,7 +473,10 @@         extensionEnabled Ext_ascii_identifiers exts = walk unEmoji       | otherwise = id     unEmoji (Span ("",["emoji"],[("data-emoji",ename)]) _) = Str ename+    unEmoji (Str t) = Str (Emoji.replaceEmojis emojisToAliases t)     unEmoji x = x+    emojisToAliases t [] = t+    emojisToAliases _ (a:_) = a  -- | Convert string to plain text identifier. textToIdentifier :: Extensions -> T.Text -> T.Text
src/Text/Pandoc/Templates.hs view
@@ -102,12 +102,12 @@        "native"  -> return ""        "csljson" -> return ""        "json"    -> return ""-       "docx"    -> return ""        "fb2"     -> return ""        "pptx"    -> return ""        "ipynb"   -> return ""        "asciidoctor" -> getDefaultTemplate "asciidoc"        "asciidoc_legacy" -> getDefaultTemplate "asciidoc"+       "docx"    -> getDefaultTemplate "openxml"        "odt"     -> getDefaultTemplate "opendocument"        "html"    -> getDefaultTemplate "html5"        "docbook" -> getDefaultTemplate "docbook5"
src/Text/Pandoc/Writers/Docx.hs view
@@ -27,1682 +27,752 @@       toArchive,       toEntry,       Entry(eRelativePath) )-import Control.Applicative ((<|>))-import Control.Monad (MonadPlus(mplus), unless, when, foldM)-import Control.Monad.Except (catchError, throwError)-import Control.Monad.Reader-    ( asks, MonadReader(local), MonadTrans(lift), ReaderT(runReaderT) )-import Control.Monad.State.Strict ( StateT(runStateT), gets, modify )-import qualified Data.ByteString.Lazy as BL-import Data.Containers.ListUtils (nubOrd)-import Data.Char (isSpace, isLetter)-import Data.List (intercalate, isPrefixOf, isSuffixOf, sortBy)-import Data.Ord (comparing)-import Data.String (fromString)-import qualified Data.Map as M-import Data.Maybe (fromMaybe, isNothing, mapMaybe, maybeToList, isJust)-import qualified Data.Set as Set-import qualified Data.Text as T-import Data.Text (Text)-import qualified Data.Text.Lazy as TL-import Data.Time.Clock.POSIX-import Data.Digest.Pure.SHA (sha1, showDigest)-import Skylighting-import Text.Pandoc.Class (PandocMonad, report, toLang, getMediaBag)-import Text.Pandoc.Translations (Term(Abstract), translateTerm)-import Text.Pandoc.MediaBag (lookupMedia, MediaItem(..))-import qualified Text.Pandoc.Translations as Term-import qualified Text.Pandoc.Class.PandocMonad as P-import Text.Pandoc.Data (readDataFile, readDefaultDataFile)-import Data.Time-import Text.Pandoc.UTF8 (fromTextLazy)-import Text.Pandoc.Definition-import Text.Pandoc.Generic-import Text.Pandoc.Highlighting (highlight)-import Text.Pandoc.Error-import Text.Pandoc.ImageSize-import Text.Pandoc.Logging-import Text.Pandoc.MIME (extensionFromMimeType, getMimeType, getMimeTypeDef)-import Text.Pandoc.Options-import Text.Pandoc.Readers.Docx.Parse (extractTarget)-import Text.Pandoc.Writers.Docx.StyleMap-import Text.Pandoc.Writers.Docx.Table as Table-import Text.Pandoc.Writers.Docx.Types-import Text.Pandoc.Shared-import Text.Pandoc.Walk-import qualified Text.Pandoc.Writers.GridTable as Grid-import Text.Pandoc.Writers.Math-import Text.Pandoc.Writers.Shared-import Text.TeXMath-import Text.Pandoc.Writers.OOXML-import Text.Pandoc.XML.Light as XML-import Data.Generics (mkT, everywhere)-import Text.Collate.Lang (renderLang, Lang(..))---- from wml.xsd EG_RPrBase-rPrTagOrder :: M.Map Text Int-rPrTagOrder =-  M.fromList-  (zip [ "rStyle"-    , "rFonts"-    , "b"-    , "bCs"-    , "i"-    , "iCs"-    , "caps"-    , "smallCaps"-    , "strike"-    , "dstrike"-    , "outline"-    , "shadow"-    , "emboss"-    , "imprint"-    , "noProof"-    , "snapToGrid"-    , "vanish"-    , "webHidden"-    , "color"-    , "spacing"-    , "w"-    , "kern"-    , "position"-    , "sz"-    , "szCs"-    , "highlight"-    , "u"-    , "effect"-    , "bdr"-    , "shd"-    , "fitText"-    , "vertAlign"-    , "rtl"-    , "cs"-    , "em"-    , "lang"-    , "eastAsianLayout"-    , "specVanish"-    , "oMath"-    ] [0..])--sortSquashed :: [Element] -> [Element]-sortSquashed l =-  sortBy (comparing tagIndex) l-  where-    tagIndex :: Element -> Int-    tagIndex el =-      fromMaybe 0 (M.lookup tag rPrTagOrder)-      where tag = (qName . elName) el--squashProps :: EnvProps -> [Element]-squashProps (EnvProps Nothing es) = sortSquashed es-squashProps (EnvProps (Just e) es) = sortSquashed (e : es)--renumIdMap :: Int -> [Element] -> M.Map Text Text-renumIdMap _ [] = M.empty-renumIdMap n (e:es)-  | Just oldId <- findAttr (QName "Id" Nothing Nothing) e =-      M.insert oldId ("rId" <> tshow n) (renumIdMap (n+1) es)-  | otherwise = renumIdMap n es--replaceAttr :: (QName -> Bool) -> Text -> [XML.Attr] -> [XML.Attr]-replaceAttr f val = map $-    \a -> if f (attrKey a) then XML.Attr (attrKey a) val else a--renumId :: (QName -> Bool) -> M.Map Text Text -> Element -> Element-renumId f renumMap e-  | Just oldId <- findAttrBy f e-  , Just newId <- M.lookup oldId renumMap =-    let attrs' = replaceAttr f newId (elAttribs e)-    in-     e { elAttribs = attrs' }-  | otherwise = e--renumIds :: (QName -> Bool) -> M.Map Text Text -> [Element] -> [Element]-renumIds f renumMap = map (renumId f renumMap)---- | Certain characters are invalid in XML even if escaped.--- See #1992-stripInvalidChars :: Text -> Text-stripInvalidChars = T.filter isValidChar---- | See XML reference-isValidChar :: Char -> Bool-isValidChar '\t' = True-isValidChar '\n' = True-isValidChar '\r' = True-isValidChar '\xFFFE' = False-isValidChar '\xFFFF' = False-isValidChar c = (' ' <= c && c <= '\xD7FF') || ('\xE000' <= c)--writeDocx :: (PandocMonad m)-          => WriterOptions  -- ^ Writer options-          -> Pandoc         -- ^ Document to convert-          -> m BL.ByteString-writeDocx opts doc = do-  let Pandoc meta blocks = walk fixDisplayMath doc-  setupTranslations meta-  let blocks' = makeSections True Nothing blocks-  let doc' = Pandoc meta blocks'--  username <- P.lookupEnv "USERNAME"-  utctime <- P.getTimestamp-  oldUserDataDir <- P.getUserDataDir-  P.setUserDataDir Nothing-  res <- readDefaultDataFile "reference.docx"-  P.setUserDataDir oldUserDataDir-  let distArchive = toArchive $ BL.fromStrict res-  refArchive <- case writerReferenceDoc opts of-                     Just f  -> toArchive . BL.fromStrict . fst-                                   <$> P.fetchItem (T.pack f)-                     Nothing -> toArchive . BL.fromStrict <$>-                          readDataFile "reference.docx"--  parsedDoc <- parseXml refArchive distArchive "word/document.xml"-  let wname f qn = qPrefix qn == Just "w" && f (qName qn)-  let mbsectpr = filterElementName (wname (=="sectPr")) parsedDoc--  -- Gets the template size-  let mbpgsz = mbsectpr >>= filterElementName (wname (=="pgSz"))-  let mbAttrSzWidth = mbpgsz >>= lookupAttrBy ((=="w") . qName) . elAttribs--  let mbpgmar = mbsectpr >>= filterElementName (wname (=="pgMar"))-  let mbAttrMarLeft = mbpgmar >>= lookupAttrBy ((=="left") . qName) . elAttribs-  let mbAttrMarRight = mbpgmar >>= lookupAttrBy ((=="right") . qName) . elAttribs--  -- Get the available area (converting the size and the margins to int and-  -- doing the difference-  let pgContentWidth = do-                         w <- mbAttrSzWidth >>= safeRead-                         r <- mbAttrMarRight >>= safeRead-                         l <- mbAttrMarLeft >>= safeRead-                         pure $ w - r - l--  -- styles-  mblang <- toLang $ getLang opts meta-  -- TODO FIXME avoid this generic traversal!-  -- lang is in w:docDefaults /  w:rPr  /  w:lang-  let addLang :: Element -> Element-      addLang = case mblang of-                  Nothing -> id-                  Just l  -> everywhere (mkT (go l))-        where-          go :: Lang -> Element -> Element-          go lang e'-           | qName (elName e') == "lang"-             = if isEastAsianLang lang-                  then e'{ elAttribs =-                             map (setattr "eastAsia" (renderLang lang)) $-                             elAttribs e' }-                  else-                    if isBidiLang lang-                       then e'{ elAttribs =-                                 map (setattr "bidi" (renderLang lang)) $-                                 elAttribs e' }-                       else e'{ elAttribs =-                                 map (setattr "val" (renderLang lang)) $-                                 elAttribs e' }-           | otherwise = e'--          setattr attrname l (XML.Attr qn@(QName s _ _) _)-            | s == attrname  = XML.Attr qn l-          setattr _ _ x      = x--          isEastAsianLang Lang{ langLanguage = lang } =-             lang == "zh" || lang == "jp" || lang == "ko"-          isBidiLang Lang{ langLanguage = lang } =-             lang == "he" || lang == "ar"--  let stylepath = "word/styles.xml"-  styledoc <- addLang <$> parseXml refArchive distArchive stylepath--  -- parse styledoc for heading styles-  let styleMaps = getStyleMaps refArchive--  let tocTitle = case lookupMetaInlines "toc-title" meta of-                   [] -> stTocTitle defaultWriterState-                   ls -> ls--  let initialSt = defaultWriterState {-          stStyleMaps  = styleMaps-        , stTocTitle   = tocTitle-        , stCurId      = 20-        }--  let isRTLmeta = case lookupMeta "dir" meta of-        Just (MetaString "rtl")        -> True-        Just (MetaInlines [Str "rtl"]) -> True-        _                              -> False--  let env = defaultWriterEnv {-          envRTL = isRTLmeta-        , envChangesAuthor = fromMaybe "unknown" username-        , envChangesDate   = T.pack $ formatTime defaultTimeLocale "%FT%XZ" utctime-        , envPrintWidth = maybe 420 (`quot` 20) pgContentWidth-        }---  ((contents, footnotes, comments), st) <- runStateT-                         (runReaderT-                          (writeOpenXML opts{writerWrapText = WrapNone} doc')-                          env)-                         initialSt-  let epochtime = floor $ utcTimeToPOSIXSeconds utctime-  let imgs = M.elems $ stImages st--  -- create entries for images in word/media/...-  let toImageEntry (_,path,_,img) = toEntry ("word/" ++ path) epochtime $ toLazy img-  let imageEntries = map toImageEntry imgs--  let stdAttributes =-            [("xmlns:w","http://schemas.openxmlformats.org/wordprocessingml/2006/main")-            ,("xmlns:m","http://schemas.openxmlformats.org/officeDocument/2006/math")-            ,("xmlns:r","http://schemas.openxmlformats.org/officeDocument/2006/relationships")-            ,("xmlns:o","urn:schemas-microsoft-com:office:office")-            ,("xmlns:v","urn:schemas-microsoft-com:vml")-            ,("xmlns:w10","urn:schemas-microsoft-com:office:word")-            ,("xmlns:a","http://schemas.openxmlformats.org/drawingml/2006/main")-            ,("xmlns:pic","http://schemas.openxmlformats.org/drawingml/2006/picture")-            ,("xmlns:wp","http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing")]---  parsedRels <- parseXml refArchive distArchive "word/_rels/document.xml.rels"-  let isHeaderNode e = findAttr (QName "Type" Nothing Nothing) e == Just "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header"-  let isFooterNode e = findAttr (QName "Type" Nothing Nothing) e == Just "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer"-  let headers = filterElements isHeaderNode parsedRels-  let footers = filterElements isFooterNode parsedRels--  -- we create [Content_Types].xml and word/_rels/document.xml.rels-  -- from scratch rather than reading from reference.docx,-  -- because Word sometimes changes these files when a reference.docx is modified,-  -- e.g. deleting the reference to footnotes.xml or removing default entries-  -- for image content types.--  -- [Content_Types].xml-  let mkOverrideNode (part', contentType') = mknode "Override"-               [("PartName", T.pack part')-               ,("ContentType", contentType')] ()-  let mkImageOverride (_, imgpath, mbMimeType, _) =-          mkOverrideNode ("/word/" <> imgpath,-                          fromMaybe "application/octet-stream" mbMimeType)-  let mkMediaOverride imgpath =-          mkOverrideNode ("/" <> imgpath, getMimeTypeDef imgpath)-  let overrides = map mkOverrideNode (-                  [("/word/webSettings.xml",-                    "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml")-                  ,("/word/numbering.xml",-                    "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml")-                  ,("/word/settings.xml",-                    "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml")-                  ,("/word/theme/theme1.xml",-                    "application/vnd.openxmlformats-officedocument.theme+xml")-                  ,("/word/fontTable.xml",-                    "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml")-                  ,("/docProps/app.xml",-                    "application/vnd.openxmlformats-officedocument.extended-properties+xml")-                  ,("/docProps/core.xml",-                    "application/vnd.openxmlformats-package.core-properties+xml")-                  ,("/docProps/custom.xml",-                    "application/vnd.openxmlformats-officedocument.custom-properties+xml")-                  ,("/word/styles.xml",-                    "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml")-                  ,("/word/document.xml",-                    "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml")-                  ,("/word/comments.xml",-                    "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml")-                  ,("/word/footnotes.xml",-                    "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml")-                  ] ++-                  map (\x -> (maybe "" (T.unpack . ("/word/" <>)) (extractTarget x),-                       "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml")) headers ++-                  map (\x -> (maybe "" (T.unpack . ("/word/" <>)) (extractTarget x),-                       "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml")) footers) ++-                    map mkImageOverride imgs ++-                    [ mkMediaOverride (eRelativePath e)-                        | e <- zEntries refArchive-                        , "word/media/" `isPrefixOf` eRelativePath e ]--  let mkDefaultNode (ext, mt) =-        mknode "Default" [("Extension",ext),("ContentType",mt)] ()-  let defaultnodes = map mkDefaultNode-        [("xml", "application/xml"),-         ("rels", "application/vnd.openxmlformats-package.relationships+xml"),-         ("odttf",-           "application/vnd.openxmlformats-officedocument.obfuscatedFont")]-  let contentTypesDoc = mknode "Types" [("xmlns","http://schemas.openxmlformats.org/package/2006/content-types")] $ defaultnodes ++ overrides-  let contentTypesEntry = toEntry "[Content_Types].xml" epochtime-        $ renderXml contentTypesDoc--  -- word/_rels/document.xml.rels-  let toBaseRel (url', id', target') = mknode "Relationship"-                                          [("Type",url')-                                          ,("Id",id')-                                          ,("Target",target')] ()-  let baserels' = map toBaseRel-                    [("http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",-                      "rId1",-                      "numbering.xml")-                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",-                      "rId2",-                      "styles.xml")-                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",-                      "rId3",-                      "settings.xml")-                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings",-                      "rId4",-                      "webSettings.xml")-                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",-                      "rId5",-                      "fontTable.xml")-                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",-                      "rId6",-                      "theme/theme1.xml")-                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",-                      "rId7",-                      "footnotes.xml")-                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",-                      "rId8",-                      "comments.xml")-                    ]--  let idMap = renumIdMap (length baserels' + 1) (headers ++ footers)-  let renumHeaders = renumIds (\q -> qName q == "Id") idMap headers-  let renumFooters = renumIds (\q -> qName q == "Id") idMap footers-  let baserels = baserels' ++ renumHeaders ++ renumFooters-  let toImgRel (ident,path,_,_) =  mknode "Relationship" [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"),("Id",T.pack ident),("Target",T.pack path)] ()-  let imgrels = map toImgRel imgs-  let toLinkRel (src,ident) =  mknode "Relationship" [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"),("Id",ident),("Target",src),("TargetMode","External") ] ()-  let linkrels = map toLinkRel $ M.toList $ stExternalLinks st-  let reldoc = mknode "Relationships" [("xmlns","http://schemas.openxmlformats.org/package/2006/relationships")] $ baserels ++ imgrels ++ linkrels-  let relEntry = toEntry "word/_rels/document.xml.rels" epochtime-        $ renderXml reldoc---  -- adjust contents to add sectPr from reference.docx-  let sectpr = case mbsectpr of-        Just sectpr' -> let cs = renumIds-                                 (\q -> qName q == "id" && qPrefix q == Just "r")-                                 idMap-                                 (elChildren sectpr')-                        in-                         add_attrs (elAttribs sectpr') $ mknode "w:sectPr" [] cs-        Nothing      -> mknode "w:sectPr" [] ()--  -- let sectpr = fromMaybe (mknode "w:sectPr" [] ()) mbsectpr'-  let contents' = contents ++ [Elem sectpr]-  let docContents = mknode "w:document" stdAttributes-                    $ mknode "w:body" [] contents'----  -- word/document.xml-  let contentEntry = toEntry "word/document.xml" epochtime-                     $ renderXml docContents--  -- footnotes-  let notes = mknode "w:footnotes" stdAttributes footnotes-  let footnotesEntry = toEntry "word/footnotes.xml" epochtime $ renderXml notes--  -- footnote rels-  let footnoteRelEntry = toEntry "word/_rels/footnotes.xml.rels" epochtime-        $ renderXml $ mknode "Relationships" [("xmlns","http://schemas.openxmlformats.org/package/2006/relationships")]-        linkrels--  -- comments-  let commentsEntry = toEntry "word/comments.xml" epochtime-        $ renderXml $ mknode "w:comments" stdAttributes comments--  -- styles--  -- We only want to inject paragraph and text properties that-  -- are not already in the style map. Note that keys in the stylemap-  -- are normalized as lowercase.-  let newDynamicParaProps = filter-        (\sty -> not $ hasStyleName sty $ smParaStyle styleMaps)-        (Set.toList $ stDynamicParaProps st)--      newDynamicTextProps = filter-        (\sty -> not $ hasStyleName sty $ smCharStyle styleMaps)-        (Set.toList $ stDynamicTextProps st)--  let newstyles = map newParaPropToOpenXml newDynamicParaProps ++-                  map newTextPropToOpenXml newDynamicTextProps ++-                  maybe [] (styleToOpenXml styleMaps) (writerHighlightStyle opts)-  let styledoc' = styledoc{ elContent = elContent styledoc ++-                                           map Elem newstyles }-  let styleEntry = toEntry stylepath epochtime $ renderXml styledoc'--  -- construct word/numbering.xml-  let numpath = "word/numbering.xml"-  numbering <- parseXml refArchive distArchive numpath-  let newNumElts = mkNumbering (stLists st)-  let pandocAdded e =-       case findAttrBy ((== "abstractNumId") . qName) e >>= safeRead of-         Just numid -> numid >= (990 :: Int)-         Nothing    ->-           case findAttrBy ((== "numId") . qName) e >>= safeRead of-             Just numid -> numid >= (1000 :: Int)-             Nothing    -> False-  let oldElts = filter (not . pandocAdded) $ onlyElems (elContent numbering)-  let allElts = oldElts ++ newNumElts-  let numEntry = toEntry numpath epochtime $ renderXml numbering{ elContent =-                       -- we want all the abstractNums first, then the nums,-                       -- otherwise things break:-                       [Elem e | e <- allElts-                               , qName (elName e) == "abstractNum" ] ++-                       [Elem e | e <- allElts-                               , qName (elName e) == "num" ] }--  let keywords = case lookupMeta "keywords" meta of-                       Just (MetaList xs) -> map stringify xs-                       _                  -> []--  -- docProps/core.xml-  let docPropsPath = "docProps/core.xml"-  let extraCoreProps = ["subject","lang","category","description"]-  let extraCorePropsMap = M.fromList $ zip extraCoreProps-                       ["dc:subject","dc:language","cp:category","dc:description"]-  let lookupMetaString' :: Text -> Meta -> Text-      lookupMetaString' key' meta' =-        case key' of-             "description"    -> T.intercalate "_x000d_\n" (map stringify $ lookupMetaBlocks "description" meta')-             key''            -> lookupMetaString key'' meta'--  let docProps = mknode "cp:coreProperties"-          [("xmlns:cp","http://schemas.openxmlformats.org/package/2006/metadata/core-properties")-          ,("xmlns:dc","http://purl.org/dc/elements/1.1/")-          ,("xmlns:dcterms","http://purl.org/dc/terms/")-          ,("xmlns:dcmitype","http://purl.org/dc/dcmitype/")-          ,("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance")]-          $ mktnode "dc:title" [] (stringify $ docTitle meta)-          : mktnode "dc:creator" [] (T.intercalate "; " (map stringify $ docAuthors meta))-          : [ mktnode (M.findWithDefault "" k extraCorePropsMap) [] (lookupMetaString' k meta)-            | k <- M.keys (unMeta meta), k `elem` extraCoreProps]-          ++ mknode "cp:keywords" [] (T.intercalate ", " keywords)-          : (\x -> [ mknode "dcterms:created" [("xsi:type","dcterms:W3CDTF")] x-                   , mknode "dcterms:modified" [("xsi:type","dcterms:W3CDTF")] x-                   ]) (T.pack $ formatTime defaultTimeLocale "%FT%XZ" utctime)-  let docPropsEntry = toEntry docPropsPath epochtime $ renderXml docProps--  -- docProps/custom.xml-  let customProperties :: [(Text, Text)]-      customProperties = [ (k, lookupMetaString k meta)-                         | k <- M.keys (unMeta meta)-                         , k `notElem` (["title", "author", "keywords"]-                                       ++ extraCoreProps)]-  let mkCustomProp (k, v) pid = mknode "property"-         [("fmtid","{D5CDD505-2E9C-101B-9397-08002B2CF9AE}")-         ,("pid", tshow pid)-         ,("name", k)] $ mknode "vt:lpwstr" [] v-  let customPropsPath = "docProps/custom.xml"-  let customProps = mknode "Properties"-          [("xmlns","http://schemas.openxmlformats.org/officeDocument/2006/custom-properties")-          ,("xmlns:vt","http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes")-          ] $ zipWith mkCustomProp customProperties [(2 :: Int)..]-  let customPropsEntry = toEntry customPropsPath epochtime $ renderXml customProps--  let relsPath = "_rels/.rels"-  let rels = mknode "Relationships" [("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships")]-        $ map (\attrs -> mknode "Relationship" attrs ())-        [ [("Id","rId1")-          ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument")-          ,("Target","word/document.xml")]-        , [("Id","rId4")-          ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties")-          ,("Target","docProps/app.xml")]-        , [("Id","rId3")-          ,("Type","http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties")-          ,("Target","docProps/core.xml")]-        , [("Id","rId5")-          ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties")-          ,("Target","docProps/custom.xml")]-        ]-  let relsEntry = toEntry relsPath epochtime $ renderXml rels--  -- we use dist archive for settings.xml, because Word sometimes-  -- adds references to footnotes or endnotes we don't have...-  -- we do, however, copy some settings over from reference-  let settingsPath = "word/settings.xml"--  settingsEntry <- copyChildren refArchive distArchive settingsPath epochtime-                      -- note: these must go in the following order:-                     [ "writeProtection"-                     , "view"-                     , "zoom"-                     , "removePersonalInformation"-                     , "removeDateAndTime"-                     , "doNotDisplayPageBoundaries"-                     , "displayBackgroundShape"-                     , "printPostScriptOverText"-                     , "printFractionalCharacterWidth"-                     , "printFormsData"-                     , "embedTrueTypeFonts"-                     , "embedSystemFonts"-                     , "saveSubsetFonts"-                     , "saveFormsData"-                     , "mirrorMargins"-                     , "alignBordersAndEdges"-                     , "bordersDoNotSurroundHeader"-                     , "bordersDoNotSurroundFooter"-                     , "gutterAtTop"-                     , "hideSpellingErrors"-                     , "hideGrammaticalErrors"-                     , "activeWritingStyle"-                     , "proofState"-                     , "formsDesign"-                     , "attachedTemplate"-                     , "linkStyles"-                     , "stylePaneFormatFilter"-                     , "stylePaneSortMethod"-                     , "documentType"-                     , "mailMerge"-                     , "revisionView"-                     , "trackRevisions"-                     , "doNotTrackMoves"-                     , "doNotTrackFormatting"-                     , "documentProtection"-                     , "autoFormatOverride"-                     , "styleLockTheme"-                     , "styleLockQFSet"-                     , "defaultTabStop"-                     , "autoHyphenation"-                     , "consecutiveHyphenLimit"-                     , "hyphenationZone"-                     , "doNotHyphenateCaps"-                     , "showEnvelope"-                     , "summaryLength"-                     , "clickAndTypeStyle"-                     , "defaultTableStyle"-                     , "evenAndOddHeaders"-                     , "bookFoldRevPrinting"-                     , "bookFoldPrinting"-                     , "bookFoldPrintingSheets"-                     , "drawingGridHorizontalSpacing"-                     , "drawingGridVerticalSpacing"-                     , "displayHorizontalDrawingGridEvery"-                     , "displayVerticalDrawingGridEvery"-                     , "doNotUseMarginsForDrawingGridOrigin"-                     , "drawingGridHorizontalOrigin"-                     , "drawingGridVerticalOrigin"-                     , "doNotShadeFormData"-                     , "noPunctuationKerning"-                     , "characterSpacingControl"-                     , "printTwoOnOne"-                     , "strictFirstAndLastChars"-                     , "noLineBreaksAfter"-                     , "noLineBreaksBefore"-                     , "savePreviewPicture"-                     , "doNotValidateAgainstSchema"-                     , "saveInvalidXml"-                     , "ignoreMixedContent"-                     , "alwaysShowPlaceholderText"-                     , "doNotDemarcateInvalidXml"-                     , "saveXmlDataOnly"-                     , "useXSLTWhenSaving"-                     , "saveThroughXslt"-                     , "showXMLTags"-                     , "alwaysMergeEmptyNamespace"-                     , "updateFields"-                     , "hdrShapeDefaults"-                     -- , "footnotePr" -- this can cause problems, see #9522-                     -- , "endnotePr"-                     , "compat"-                     , "docVars"-                     , "rsids"-                     , "attachedSchema"-                     , "themeFontLang"-                     , "clrSchemeMapping"-                     , "doNotIncludeSubdocsInStats"-                     , "doNotAutoCompressPictures"-                     , "forceUpgrade"-                     , "captions"-                     , "readModeInkLockDown"-                     , "smartTagType"-                     , "shapeDefaults"-                     , "doNotEmbedSmartTags"-                     , "decimalSymbol"-                     , "listSeparator" ]--  let entryFromArchive arch path =-         maybe (throwError $ PandocSomeError-                           $ T.pack $ path ++ " missing in reference docx")-               return-               (findEntryByPath path arch `mplus` findEntryByPath path distArchive)-  docPropsAppEntry <- entryFromArchive refArchive "docProps/app.xml"-  themeEntry <- entryFromArchive refArchive "word/theme/theme1.xml"-  fontTableEntry <- entryFromArchive refArchive "word/fontTable.xml"-  let fontTableRelsEntries = maybeToList $-       findEntryByPath "word/_rels/fontTable.xml.rels" refArchive-  let fontEntries = [entry | entry <- zEntries refArchive-                           , "word/fonts/" `isPrefixOf` (eRelativePath entry)]-                        -- or parse fontTable.xml.rels?-  webSettingsEntry <- entryFromArchive refArchive "word/webSettings.xml"-  headerFooterEntries <- mapM (entryFromArchive refArchive . ("word/" ++)) $-                         mapMaybe (fmap T.unpack . extractTarget)-                         (headers ++ footers)-  let miscRelEntries = [ e | e <- zEntries refArchive-                       , "word/_rels/" `isPrefixOf` eRelativePath e-                       , ".xml.rels" `isSuffixOf` eRelativePath e-                       , eRelativePath e /= "word/_rels/document.xml.rels"-                       , eRelativePath e /= "word/_rels/footnotes.xml.rels" ]-  let otherMediaEntries = [ e | e <- zEntries refArchive-                          , "word/media/" `isPrefixOf` eRelativePath e ]--  -- Create archive-  let archive = foldr addEntryToArchive emptyArchive $-                  contentTypesEntry : relsEntry : contentEntry : relEntry :-                  footnoteRelEntry : numEntry : styleEntry : footnotesEntry :-                  commentsEntry :-                  docPropsEntry : docPropsAppEntry : customPropsEntry :-                  themeEntry :-                  settingsEntry : webSettingsEntry :-                  fontTableEntry :-                  fontTableRelsEntries ++ fontEntries ++-                  imageEntries ++ headerFooterEntries ++-                  miscRelEntries ++ otherMediaEntries-  return $ fromArchive archive--newParaPropToOpenXml :: ParaStyleName -> Element-newParaPropToOpenXml (fromStyleName -> s) =-  let styleId = T.filter (not . isSpace) s-  in mknode "w:style" [ ("w:type", "paragraph")-                      , ("w:customStyle", "1")-                      , ("w:styleId", styleId)]-     [ mknode "w:name" [("w:val", s)] ()-     , mknode "w:basedOn" [("w:val","BodyText")] ()-     , mknode "w:qFormat" [] ()-     ]--newTextPropToOpenXml :: CharStyleName -> Element-newTextPropToOpenXml (fromStyleName -> s) =-  let styleId = T.filter (not . isSpace) s-  in mknode "w:style" [ ("w:type", "character")-                      , ("w:customStyle", "1")-                      , ("w:styleId", styleId)]-     [ mknode "w:name" [("w:val", s)] ()-     , mknode "w:basedOn" [("w:val","BodyTextChar")] ()-     ]--styleToOpenXml :: StyleMaps -> Style -> [Element]-styleToOpenXml sm style =-  maybeToList parStyle ++ mapMaybe toStyle alltoktypes-  where alltoktypes = enumFromTo KeywordTok NormalTok-        toStyle toktype | hasStyleName (fromString $ show toktype) (smCharStyle sm) = Nothing-                        | otherwise = Just $-                          mknode "w:style" [("w:type","character"),-                           ("w:customStyle","1"),("w:styleId", tshow toktype)]-                             [ mknode "w:name" [("w:val", tshow toktype)] ()-                             , mknode "w:basedOn" [("w:val","VerbatimChar")] ()-                             , mknode "w:rPr" [] $-                               [ mknode "w:b" [] () | tokFeature tokenBold toktype ] ++-                               [ mknode "w:i" [] () | tokFeature tokenItalic toktype ] ++-                               [ mknode "w:color" [("w:val", tokCol toktype)] ()-                                 | tokCol toktype /= "auto" ] ++-                               [ mknode "w:u" [] () | tokFeature tokenUnderline toktype ] ++-                               [ mknode "w:shd" [("w:val","clear")-                                                ,("w:fill",tokBg toktype)] ()-                                 | tokBg toktype /= "auto" ]-                             ]-        tokStyles = tokenStyles style-        tokFeature f toktype = maybe False f $ M.lookup toktype tokStyles-        tokCol toktype = maybe "auto" (T.pack . drop 1 . fromColor)-                         $ (tokenColor =<< M.lookup toktype tokStyles)-                           `mplus` defaultColor style-        tokBg toktype = maybe "auto" (T.pack . drop 1 . fromColor)-                         $ (tokenBackground =<< M.lookup toktype tokStyles)-                           `mplus` backgroundColor style-        parStyle | hasStyleName "Source Code" (smParaStyle sm) = Nothing-                 | otherwise = Just $-                   mknode "w:style" [("w:type","paragraph"),-                           ("w:customStyle","1"),("w:styleId","SourceCode")]-                             [ mknode "w:name" [("w:val","Source Code")] ()-                             , mknode "w:basedOn" [("w:val","Normal")] ()-                             , mknode "w:link" [("w:val","VerbatimChar")] ()-                             , mknode "w:pPr" []-                               $ mknode "w:wordWrap" [("w:val","off")] ()-                               :-                         maybe [] (\col -> [mknode "w:shd" [("w:val","clear"),("w:fill", T.pack $ drop 1 $ fromColor col)] ()]) (backgroundColor style)-                             ]--copyChildren :: (PandocMonad m)-             => Archive -> Archive -> String -> Integer -> [Text] -> m Entry-copyChildren refArchive distArchive path timestamp elNames = do-  ref  <- parseXml refArchive distArchive path-  dist <- parseXml distArchive distArchive path-  els <- foldM (addEl ref dist) [] (reverse elNames)-  return $ toEntry path timestamp-         $ renderXml dist{ elContent = map cleanElem els }-  where-    addEl ref dist els name =-      case filterChildName (hasName name) ref `mplus`-             filterChildName (hasName name) dist of-        Just el -> pure (el : els)-        Nothing -> pure els-    hasName name = (== name) . qName-    cleanElem el@Element{elName=name} = Elem el{elName=name{qURI=Nothing}}---- this is the lowest number used for a list numId-baseListId :: Int-baseListId = 1000--mkNumbering :: [ListMarker] -> [Element]-mkNumbering lists =-  elts ++ zipWith mkNum lists [baseListId..(baseListId + length lists - 1)]-    where elts = map mkAbstractNum (nubOrd lists)--maxListLevel :: Int-maxListLevel = 8--mkNum :: ListMarker -> Int -> Element-mkNum marker numid =-  mknode "w:num" [("w:numId",tshow numid)]-   $ mknode "w:abstractNumId" [("w:val",listMarkerToId marker)] ()-   : case marker of-       NoMarker     -> []-       BulletMarker -> []-       NumberMarker _ _ start ->-          map (\lvl -> mknode "w:lvlOverride" [("w:ilvl",tshow (lvl :: Int))]-              $ mknode "w:startOverride" [("w:val",tshow start)] ())-                [0..maxListLevel]--mkAbstractNum :: ListMarker -> Element-mkAbstractNum marker =-  mknode "w:abstractNum" [("w:abstractNumId",listMarkerToId marker)]-    $ mknode "w:nsid" [("w:val", T.justifyRight 8 '0' ("A" <> listMarkerToId marker))] ()-    : mknode "w:multiLevelType" [("w:val","multilevel")] ()-    : map (mkLvl marker)-      [0..maxListLevel]--mkLvl :: ListMarker -> Int -> Element-mkLvl marker lvl =-  mknode "w:lvl" [("w:ilvl",tshow lvl)] $-    [ mknode "w:start" [("w:val",start)] ()-      | marker /= NoMarker && marker /= BulletMarker ] ++-    [ mknode "w:numFmt" [("w:val",fmt)] ()-    , mknode "w:lvlText" [("w:val", lvltxt)] ()-    , mknode "w:lvlJc" [("w:val","left")] ()-    , mknode "w:pPr" [] $-        mknode "w:ind" [ ("w:left",tshow $ lvl * step + step)-                       , ("w:hanging",tshow hang)-                       ] ()-    ] ++-    maybe [] (\font ->-                [ mknode "w:rPr" []-                  [ mknode "w:rFonts" [ ("w:ascii", font)-                                      , ("w:hAnsi", font)-                                      , ("w:cs", font)-                                      , ("w:hint", "default") ] () ]]) mbfont-    where (fmt, lvltxt, mbfont, start) =-            case marker of-                 NoMarker             -> ("bullet"," ", Nothing, "1")-                 BulletMarker         -> bulletFor lvl-                 NumberMarker st de n -> (styleFor st lvl-                                         ,patternFor de ("%" <> tshow (lvl + 1))-                                         ,Nothing-                                         ,tshow n)-          step = 720-          hang :: Int-          hang = 360-          bulletFor 0 = ("bullet", "\xf0b7", Just "Symbol", "1") -- filled circle-          bulletFor 1 = ("bullet", "o", Just "Courier New", "1") -- open o-          bulletFor 2 = ("bullet", "\xf0a7", Just "Wingdings", "1")  -- closed box-          bulletFor x = bulletFor (x `mod` 3)-          styleFor UpperAlpha _   = "upperLetter"-          styleFor LowerAlpha _   = "lowerLetter"-          styleFor UpperRoman _   = "upperRoman"-          styleFor LowerRoman _   = "lowerRoman"-          styleFor Decimal _      = "decimal"-          styleFor DefaultStyle 0 = "decimal"-          styleFor DefaultStyle 1 = "lowerLetter"-          styleFor DefaultStyle 2 = "lowerRoman"-          styleFor DefaultStyle 3 = "decimal"-          styleFor DefaultStyle 4 = "lowerLetter"-          styleFor DefaultStyle 5 = "lowerRoman"-          styleFor DefaultStyle x = styleFor DefaultStyle (x `mod` 6)-          styleFor _ _            = "decimal"-          patternFor OneParen s  = s <> ")"-          patternFor TwoParens s = "(" <> s <> ")"-          patternFor _ s         = s <> "."--getNumId :: (PandocMonad m) => WS m Int-getNumId = (((baseListId - 1) +) . length) `fmap` gets stLists---makeTOC :: (PandocMonad m) => WriterOptions -> WS m [Element]-makeTOC opts = do-  let depth = "1-" <> tshow (writerTOCDepth opts)-  let tocCmd = "TOC \\o \"" <> depth <> "\" \\h \\z \\u"-  tocTitle <- gets stTocTitle-  title <- withParaPropM (pStyleM "TOC Heading") (blocksToOpenXML opts [Para tocTitle])-  return-    [mknode "w:sdt" [] [-      mknode "w:sdtPr" [] (-        mknode "w:docPartObj" []-          [mknode "w:docPartGallery" [("w:val","Table of Contents")] (),-          mknode "w:docPartUnique" [] ()]-         -- w:docPartObj-      ), -- w:sdtPr-      mknode "w:sdtContent" [] (title ++ [ Elem $-        mknode "w:p" [] (-          mknode "w:r" [] [-            mknode "w:fldChar" [("w:fldCharType","begin"),("w:dirty","true")] (),-            mknode "w:instrText" [("xml:space","preserve")] tocCmd,-            mknode "w:fldChar" [("w:fldCharType","separate")] (),-            mknode "w:fldChar" [("w:fldCharType","end")] ()-          ] -- w:r-        ) -- w:p-      ])-    ]] -- w:sdt---- | Convert Pandoc document to two lists of--- OpenXML elements (the main document and footnotes).-writeOpenXML :: (PandocMonad m)-             => WriterOptions -> Pandoc-             -> WS m ([Content], [Element], [Element])-writeOpenXML opts (Pandoc meta blocks) = do-  let tit = docTitle meta-  let auths = docAuthors meta-  let dat = docDate meta-  let abstract' = lookupMetaBlocks "abstract" meta-  let subtitle' = lookupMetaInlines "subtitle" meta-  let includeTOC = writerTableOfContents opts || lookupMetaBool "toc" meta-  title <- withParaPropM (pStyleM "Title") $ blocksToOpenXML opts [Para tit | not (null tit)]-  subtitle <- withParaPropM (pStyleM "Subtitle") $ blocksToOpenXML opts [Para subtitle' | not (null subtitle')]-  authors <- withParaPropM (pStyleM "Author") $ blocksToOpenXML opts $-       map Para auths-  date <- withParaPropM (pStyleM "Date") $ blocksToOpenXML opts [Para dat | not (null dat)]-  abstract <- if null abstract'-                 then return []-                 else do-                   abstractTitle <- case lookupMeta "abstract-title" meta of-                       Just (MetaBlocks bs)   -> pure $ stringify bs-                       Just (MetaInlines ils) -> pure $ stringify ils-                       Just (MetaString s)    -> pure s-                       _                      -> translateTerm Abstract-                   abstractTit <- withParaPropM (pStyleM "AbstractTitle") $-                                   blocksToOpenXML opts-                                     [Para [Str abstractTitle]]-                   abstractContents <- withParaPropM (pStyleM "Abstract") $-                                         blocksToOpenXML opts abstract'-                   return $ abstractTit <> abstractContents--  let convertSpace (Str x : Space : Str y : xs) = Str (x <> " " <> y) : xs-      convertSpace (Str x : Str y : xs)         = Str (x <> y) : xs-      convertSpace xs                           = xs-  let blocks' = bottomUp convertSpace blocks-  doc' <- setFirstPara >> blocksToOpenXML opts blocks'-  notes' <- reverse <$> gets stFootnotes-  comments <- reverse <$> gets stComments-  let toComment (kvs, ils) = do-        annotation <- inlinesToOpenXML opts ils-        return $-          mknode "w:comment" [("w:" <> k, v) | (k,v) <- kvs]-            [ mknode "w:p" [] $-              map Elem-              [ mknode "w:pPr" []-                [ mknode "w:pStyle" [("w:val", "CommentText")] () ]-              , mknode "w:r" []-                [ mknode "w:rPr" []-                  [ mknode "w:rStyle" [("w:val", "CommentReference")] ()-                  ]-                  , mknode "w:annotationRef" [] ()-                ]-              ] ++ annotation-            ]-  comments' <- mapM toComment comments-  toc <- if includeTOC-            then makeTOC opts-            else return []-  let meta' = title ++ subtitle ++ authors ++ date ++ abstract ++ map Elem toc-  return (meta' ++ doc', notes', comments')---- | Convert a list of Pandoc blocks to OpenXML.-blocksToOpenXML :: (PandocMonad m) => WriterOptions -> [Block] -> WS m [Content]-blocksToOpenXML opts = fmap concat . mapM (blockToOpenXML opts) . separateTables . filter (not . isForeignRawBlock)--isForeignRawBlock :: Block -> Bool-isForeignRawBlock (RawBlock format _) = format /= "openxml"-isForeignRawBlock _                   = False---- Word combines adjacent tables unless you put an empty paragraph between--- them.  See #4315.-separateTables :: [Block] -> [Block]-separateTables [] = []-separateTables (x@Table{}:xs@(Table{}:_)) =-  x : RawBlock (Format "openxml") "<w:p />" : separateTables xs-separateTables (x:xs) = x : separateTables xs--rStyleM :: (PandocMonad m) => CharStyleName -> WS m XML.Element-rStyleM styleName = do-  cStyleMap <- gets (smCharStyle . stStyleMaps)-  let sty' = getStyleIdFromName styleName cStyleMap-  return $ mknode "w:rStyle" [("w:val", fromStyleId sty')] ()--getUniqueId :: (PandocMonad m) => WS m Text-getUniqueId = do-  n <- gets stCurId-  modify $ \st -> st{stCurId = n + 1}-  return $ tshow n---- | Key for specifying user-defined docx styles.-dynamicStyleKey :: Text-dynamicStyleKey = "custom-style"---- | Convert a Pandoc block element to OpenXML.-blockToOpenXML :: (PandocMonad m) => WriterOptions -> Block -> WS m [Content]-blockToOpenXML opts blk = withDirection $ blockToOpenXML' opts blk--blockToOpenXML' :: (PandocMonad m) => WriterOptions -> Block -> WS m [Content]-blockToOpenXML' opts (Div (ident,_classes,kvs) bs) = do-  stylemod <- case lookup dynamicStyleKey kvs of-                   Just (fromString . T.unpack -> sty) -> do-                      modify $ \s ->-                        s{stDynamicParaProps = Set.insert sty-                             (stDynamicParaProps s)}-                      return $ withParaPropM (pStyleM sty)-                   _ -> return id-  dirmod <- case lookup "dir" kvs of-                 Just "rtl" -> return $ local (\env -> env { envRTL = True })-                 Just "ltr" -> return $ local (\env -> env { envRTL = False })-                 _ -> return id-  let (hs, bs') = if ident == "refs"-                     then span isHeaderBlock bs-                     else ([], bs)-  let bibmod = if ident == "refs"-                  then withParaPropM (pStyleM "Bibliography")-                  else id-  let langmod = case lookup "lang" kvs of-                  Nothing -> id-                  Just lang -> local (\env -> env{envLang = Just lang})-  header <- dirmod $ stylemod $ blocksToOpenXML opts hs-  contents <- dirmod $ bibmod $ stylemod $ langmod $ blocksToOpenXML opts bs'-  wrapBookmark ident $ header <> contents-blockToOpenXML' opts (Header lev (ident,_,kvs) lst) = do-  setFirstPara-  paraProps <- withParaPropM (pStyleM (fromString $ "Heading "++show lev)) $-                    getParaProps False-  number <--        if writerNumberSections opts-           then-             case lookup "number" kvs of-                Just n -> do-                   num <- withTextPropM (rStyleM "SectionNumber")-                            (inlineToOpenXML opts (Str n))-                   return $ num ++ [Elem $ mknode "w:r" [] [mknode "w:tab" [] ()]]-                Nothing -> return []-           else return []-  contents <- (number ++) <$> inlinesToOpenXML opts lst-  if T.null ident-     then return [Elem $ mknode "w:p" [] (map Elem paraProps ++ contents)]-     else do-       let bookmarkName = ident-       modify $ \s -> s{ stSectionIds = Set.insert bookmarkName-                                      $ stSectionIds s }-       bookmarkedContents <- wrapBookmark bookmarkName contents-       return [Elem $ mknode "w:p" [] (map Elem paraProps ++ bookmarkedContents)]-blockToOpenXML' opts (Plain lst) = do-  isInTable <- gets stInTable-  isInList <- gets stInList-  let block = blockToOpenXML opts (Para lst)-  prop <- pStyleM "Compact"-  if isInTable || isInList-     then withParaProp prop block-     else block-blockToOpenXML' opts (Para lst)-  | null lst && not (isEnabled Ext_empty_paragraphs opts) = return []-  | otherwise = do-      isFirstPara <- gets stFirstPara-      let displayMathPara = case lst of-                                 [x] -> isDisplayMath x-                                 _   -> False-      paraProps <- getParaProps displayMathPara-      bodyTextStyle <- pStyleM $ if isFirstPara-                       then "First Paragraph"-                       else "Body Text"-      let paraProps' = case paraProps of-            []               -> [mknode "w:pPr" [] [bodyTextStyle]]-            ps               -> ps-      modify $ \s -> s { stFirstPara = False }-      contents <- inlinesToOpenXML opts lst-      return [Elem $ mknode "w:p" [] (map Elem paraProps' ++ contents)]-blockToOpenXML' opts (LineBlock lns) = blockToOpenXML opts $ linesToPara lns-blockToOpenXML' _ b@(RawBlock format str)-  | format == Format "openxml" = return [-        Text (CData CDataRaw str Nothing)-      ]-  | otherwise                  = do-      report $ BlockNotRendered b-      return []-blockToOpenXML' opts (BlockQuote blocks) = do-  inNote <- asks envInNote-  p <- withParaPropM (pStyleM-                       (if inNote-                           then "Footnote Block Text"-                           else "Block Text"))-       $ blocksToOpenXML opts blocks-  setFirstPara-  return p-blockToOpenXML' opts (CodeBlock attrs@(ident, _, _) str) = do-  p <- withParaPropM (pStyleM "Source Code") (blockToOpenXML opts $ Para [Code attrs str])-  setFirstPara-  wrapBookmark ident p-blockToOpenXML' _ HorizontalRule = do-  setFirstPara-  return [ Elem $-    mknode "w:p" [] $ mknode "w:r" [] $ mknode "w:pict" []-    $ mknode "v:rect" [("style","width:0;height:1.5pt"),-                       ("o:hralign","center"),-                       ("o:hrstd","t"),("o:hr","t")] () ]-blockToOpenXML' opts (Table attr caption colspecs thead tbodies tfoot) = do-  -- Remove extra paragraph indentation due to list items (#5947).-  -- This means that tables in lists will not be indented, but it-  -- avoids unwanted indentation in each cell.-  content <- tableToOpenXML opts-              (local (\env -> env{ envListLevel = -1 }) . blocksToOpenXML opts)-                 (Grid.toTable attr caption colspecs thead tbodies tfoot)-  let (tableId, _, _) = attr-  wrapBookmark tableId content-blockToOpenXML' opts el-  | BulletList lst <- el = addOpenXMLList BulletMarker lst-  | OrderedList (start, numstyle, numdelim) lst <- el-  = addOpenXMLList (NumberMarker numstyle numdelim start) lst-  where-    addOpenXMLList marker lst = do-      addList marker-      numid  <- getNumId-      exampleid <- case marker of-                        NumberMarker Example _ _ -> gets stExampleId-                        _ -> return Nothing-      l <- asList $ concat `fmap` mapM (listItemToOpenXML opts $ fromMaybe numid exampleid) lst-      setFirstPara-      return l-blockToOpenXML' opts (DefinitionList items) = do-  l <- concat `fmap` mapM (definitionListItemToOpenXML opts) items-  setFirstPara-  return l-blockToOpenXML' opts (Figure (ident, _, _) (Caption _ longcapt) body) = do-  setFirstPara-  fignum <- gets stNextFigureNum-  unless (null longcapt) $ modify $ \st -> st{ stNextFigureNum = fignum + 1 }-  let refid = if T.null ident-              then "ref_fig" <> tshow fignum-              else "ref_" <> ident-  figname <- translateTerm Term.Figure-  prop <- pStyleM $-    if null longcapt-    then "Figure"-    else "Captioned Figure"-  paraProps <- local-    (\env -> env { envParaProperties = EnvProps (Just prop) [] <>-                                       envParaProperties env })-    (getParaProps False)--  -- Figure contents-  let simpleImage x = do-        imgXML <- inlineToOpenXML opts x-        pure $ Elem (mknode "w:p" [] (map Elem paraProps ++ imgXML))-  contentsNode <- case body of-    [Plain [img@Image {}]] -> simpleImage img-    [Para  [img@Image {}]] -> simpleImage img-    _                      -> toFigureTable opts body-  -- Caption-  let imageCaption = withParaPropM (pStyleM "Image Caption")-                   . blocksToOpenXML opts-  let fstCaptionPara inlns = Para $-        if not $ isEnabled Ext_native_numbering opts-        then inlns-        else let rawfld = RawInline (Format "openxml") $ mconcat-                          [ "<w:fldSimple w:instr=\"SEQ Figure"-                          , " \\* ARABIC \"><w:r><w:t>"-                          , tshow fignum-                          , "</w:t></w:r></w:fldSimple>"-                          ]-             in Span (refid,[],[]) [Str (figname <> "\160") , rawfld]-                : Str ": " : inlns-  captionNode <- case longcapt of-    []              -> return []-    (Para xs  : bs) -> imageCaption (fstCaptionPara xs : bs)-    (Plain xs : bs) -> imageCaption (fstCaptionPara xs : bs)-    _               -> imageCaption longcapt-  return $ contentsNode : captionNode--toFigureTable :: PandocMonad m-              => WriterOptions -> [Block] -> WS m Content-toFigureTable opts blks = do-  modify $ \s -> s { stInTable = True }-  let ncols = length blks-  let textwidth = 7920  -- 5.5 in in twips       (1 twip == 1/20 pt)-  let cellfrac = 1 / fromIntegral ncols-  let colwidth = tshow @Integer $ floor (textwidth * cellfrac) -- twips-  let gridCols = replicate ncols $ mknode "w:gridCol" [("w:w", colwidth)] ()-  let scaleImage = \case-        Image attr@(ident, classes, attribs) alt tgt ->-          let dimWidth  = case dimension Width attr of-                            Nothing -> Percent (cellfrac * 100)-                            Just d  -> scaleDimension cellfrac d-              dimHeight = scaleDimension cellfrac <$> dimension Height attr-              attribs' = (tshow Width, tshow dimWidth) :-                         (case dimHeight of-                            Nothing -> id-                            Just h  -> ((tshow Height, tshow h) :))-                         [ (k, v) | (k, v) <- attribs-                                  , k `notElem` ["width", "height"]-                                  ]-          in Image (ident, classes, attribs') alt tgt-        x -> x-  let blockToCell = Table.OOXMLCell nullAttr AlignCenter 1 1 . (:[])-                  . walk scaleImage-  tblBody <- Table.rowToOpenXML (blocksToOpenXML opts) .-             Table.OOXMLRow Table.BodyRow nullAttr $-             map blockToCell blks-  let tbl = mknode "w:tbl" []-        ( mknode "w:tblPr" []-          [ mknode "w:tblStyle" [("w:val","FigureTable")] (),-            mknode "w:tblW" [ ("w:type", "auto"), ("w:w", "0") ] (),-            mknode "w:jc" [("w:val","center")] (),-            mknode "w:tblLook" [ ("w:firstRow", "0")-                               , ("w:lastRow", "0")-                               , ("w:firstColumn", "0")-                               , ("w:lastColumn", "0")-                               ] ()-          ]-          : mknode "w:tblGrid" [] gridCols-          : maybeToList tblBody-        )-  modify $ \s -> s { stInTable = False }-  return $ Elem tbl---definitionListItemToOpenXML  :: (PandocMonad m)-                             => WriterOptions -> ([Inline],[[Block]])-                             -> WS m [Content]-definitionListItemToOpenXML opts (term,defs) = do-  term' <- withParaPropM (pStyleM "Definition Term")-           $ blockToOpenXML opts (Para term)-  defs' <- withParaPropM (pStyleM "Definition")-           $ concat `fmap` mapM (blocksToOpenXML opts) defs-  return $ term' ++ defs'--addList :: (PandocMonad m) => ListMarker -> WS m ()-addList marker = do-  lists <- gets stLists-  lastExampleId <- gets stExampleId-  modify $ \st -> st{ stLists = lists ++ case marker of-                                         -- Use only first occurrence of Example for list declaration to avoid overhead-                                         NumberMarker Example _ _ | isJust lastExampleId -> []-                                         _ -> [marker]-                    , stExampleId = case marker of-                                         -- Reuse the same identifier for all other occurrences of Example-                                         NumberMarker Example _ _ -> lastExampleId <|> Just (baseListId + length lists)-                                         _ -> lastExampleId-                  }--listItemToOpenXML :: (PandocMonad m)-                  => WriterOptions-                  -> Int -> [Block]-                  -> WS m [Content]-listItemToOpenXML opts numid bs = do-  oldInList <- gets stInList-  modify $ \st -> st{ stInList = True }-  let isListBlock = \case-        BulletList{}  -> True-        OrderedList{} -> True-        _             -> False-  -- Prepend an empty string if the first entry is another-  -- list. Otherwise the outer bullet will disappear.-  let bs' = case bs of-                 [] -> []-                 first:rest -> if isListBlock first-                               then Plain [Str ""]:first:rest-                               else first:rest-  modify $ \st -> st{ stNumIdUsed = False }-  contents <- withNumId numid $ blocksToOpenXML opts bs'-  modify $ \st -> st{ stInList = oldInList }-  return contents---- | Convert a list of inline elements to OpenXML.-inlinesToOpenXML :: PandocMonad m => WriterOptions -> [Inline] -> WS m [Content]-inlinesToOpenXML opts lst = concat `fmap` mapM (inlineToOpenXML opts) lst--withNumId :: (PandocMonad m) => Int -> WS m a -> WS m a-withNumId numid = local $ \env -> env{ envListNumId = numid }--asList :: (PandocMonad m) => WS m a -> WS m a-asList = local $ \env -> env{ envListLevel = envListLevel env + 1 }--getTextProps :: (PandocMonad m) => WS m [Element]-getTextProps = do-  props <- asks envTextProperties-  mblang <- asks envLang-  let langnode = case mblang of-                   Nothing -> mempty-                   Just l  -> EnvProps Nothing-                               [mknode "w:lang" [("w:val", l)] ()]-  let squashed = squashProps (props <> langnode)-  return [mknode "w:rPr" [] squashed | (not . null) squashed]--withTextProp :: PandocMonad m => Element -> WS m a -> WS m a-withTextProp d p =-  local (\env -> env {envTextProperties = ep <> envTextProperties env}) p-  where ep = if isStyle d then EnvProps (Just d) [] else EnvProps Nothing [d]--withTextPropM :: PandocMonad m => WS m Element -> WS m a -> WS m a-withTextPropM md p = do-  d <- md-  withTextProp d p--getParaProps :: PandocMonad m => Bool -> WS m [Element]-getParaProps displayMathPara = do-  props <- asks envParaProperties-  listLevel <- asks envListLevel-  numid <- asks envListNumId-  numIdUsed <- gets stNumIdUsed-  -- clear numId after first use to support multiple paragraphs in the same bullet-  -- baseListId is the code for no list marker-  let numid' = if numIdUsed then baseListId else numid-  modify $ \st -> st{ stNumIdUsed = True }-  let listPr = [mknode "w:numPr" []-                [ mknode "w:ilvl" [("w:val",tshow listLevel)] ()-                , mknode "w:numId" [("w:val",tshow numid')] () ] | listLevel >= 0 && not displayMathPara]-  return $ case squashProps (EnvProps Nothing listPr <> props) of-                [] -> []-                ps -> [mknode "w:pPr" [] ps]--formattedString :: PandocMonad m => Text -> WS m [Element]-formattedString str =-  -- properly handle soft hyphens-  case splitTextBy (=='\173') str of-      [w] -> formattedString' w-      ws  -> do-         sh <- formattedRun [mknode "w:softHyphen" [] ()]-         intercalate sh <$> mapM formattedString' ws--formattedString' :: PandocMonad m => Text -> WS m [Element]-formattedString' str = do-  inDel <- asks envInDel-  formattedRun [ mktnode (if inDel then "w:delText" else "w:t")-                 [("xml:space","preserve")] (stripInvalidChars str) ]--formattedRun :: PandocMonad m => [Element] -> WS m [Element]-formattedRun els = do-  props <- getTextProps-  return [ mknode "w:r" [] $ props ++ els ]---- | Convert an inline element to OpenXML.-inlineToOpenXML :: PandocMonad m => WriterOptions -> Inline -> WS m [Content]-inlineToOpenXML opts il = withDirection $ inlineToOpenXML' opts il--inlineToOpenXML' :: PandocMonad m => WriterOptions -> Inline -> WS m [Content]-inlineToOpenXML' _ (Str str) =-  map Elem <$> formattedString str-inlineToOpenXML' opts Space = inlineToOpenXML opts (Str " ")-inlineToOpenXML' opts SoftBreak = inlineToOpenXML opts (Str " ")-inlineToOpenXML' opts (Span ("",["mark"],[]) ils) =-  withTextProp (mknode "w:highlight" [("w:val","yellow")] ()) $-    inlinesToOpenXML opts ils-inlineToOpenXML' opts (Span ("",["csl-block"],[]) ils) =-  inlinesToOpenXML opts ils-inlineToOpenXML' opts (Span ("",["csl-left-margin"],[]) ils) =-  inlinesToOpenXML opts ils-inlineToOpenXML' opts (Span ("",["csl-right-inline"],[]) ils) =-   ([Elem $-     mknode "w:r" []-     (mknode "w:t"-       [("xml:space","preserve")]-       ("\t" :: Text))] ++)-    <$> inlinesToOpenXML opts ils-inlineToOpenXML' opts (Span ("",["csl-indent"],[]) ils) =-  inlinesToOpenXML opts ils-inlineToOpenXML' _ (Span (ident,["comment-start"],kvs) ils) = do-  -- prefer the "id" in kvs, since that is the one produced by the docx-  -- reader.-  let ident' = fromMaybe ident (lookup "id" kvs)-      kvs' = filter (("id" /=) . fst) kvs-  modify $ \st -> st{ stComments = (("id",ident'):kvs', ils) : stComments st }-  return [ Elem $ mknode "w:commentRangeStart" [("w:id", ident')] () ]-inlineToOpenXML' _ (Span (ident,["comment-end"],kvs) _) =-  -- prefer the "id" in kvs, since that is the one produced by the docx-  -- reader.-  let ident' = fromMaybe ident (lookup "id" kvs)-  in return . map Elem $-     [ mknode "w:commentRangeEnd" [("w:id", ident')] ()-     , mknode "w:r" []-       [ mknode "w:rPr" []-         [ mknode "w:rStyle" [("w:val", "CommentReference")] () ]-       , mknode "w:commentReference" [("w:id", ident')] () ]-     ]-inlineToOpenXML' opts (Span (ident,classes,kvs) ils) = do-  stylemod <- case lookup dynamicStyleKey kvs of-                   Just (fromString . T.unpack -> sty) -> do-                      modify $ \s ->-                        s{stDynamicTextProps = Set.insert sty-                              (stDynamicTextProps s)}-                      return $ withTextPropM (rStyleM sty)-                   _ -> return id-  let dirmod = case lookup "dir" kvs of-                 Just "rtl" -> local (\env -> env { envRTL = True })-                 Just "ltr" -> local (\env -> env { envRTL = False })-                 _          -> id-      off x = withTextProp (mknode x [("w:val","0")] ())-      pmod =  (if "csl-no-emph" `elem` classes then off "w:i" else id) .-              (if "csl-no-strong" `elem` classes then off "w:b" else id) .-              (if "csl-no-smallcaps" `elem` classes-                  then off "w:smallCaps"-                  else id)-      getChangeAuthorDate = do-        defaultAuthor <- asks envChangesAuthor-        let author = fromMaybe defaultAuthor (lookup "author" kvs)-        let mdate = lookup "date" kvs-        return $ ("w:author", author) :-                   maybe [] (\date -> [("w:date", date)]) mdate-  insmod <- if "insertion" `elem` classes-               then do-                 changeAuthorDate <- getChangeAuthorDate-                 insId <- gets stInsId-                 modify $ \s -> s{stInsId = insId + 1}-                 return $ \f -> do-                   x <- f-                   return [Elem $-                           mknode "w:ins"-                             (("w:id", tshow insId) : changeAuthorDate) x]-               else return id-  delmod <- if "deletion" `elem` classes-               then do-                 changeAuthorDate <- getChangeAuthorDate-                 delId <- gets stDelId-                 modify $ \s -> s{stDelId = delId + 1}-                 return $ \f -> local (\env->env{envInDel=True}) $ do-                   x <- f-                   return [Elem $ mknode "w:del"-                             (("w:id", tshow delId) : changeAuthorDate) x]-               else return id-  let langmod = case lookup "lang" kvs of-                  Nothing -> id-                  Just lang -> local (\env -> env{envLang = Just lang})-  contents <- insmod $ delmod $ dirmod $ stylemod $ pmod $-              langmod $ inlinesToOpenXML opts ils-  wrapBookmark ident contents-inlineToOpenXML' opts (Strong lst) =-  withTextProp (mknode "w:bCs" [] ()) $ -- needed for LTR, #6911-  withTextProp (mknode "w:b" [] ()) $-  inlinesToOpenXML opts lst-inlineToOpenXML' opts (Emph lst) =-  withTextProp (mknode "w:iCs" [] ()) $  -- needed for LTR, #6911-  withTextProp (mknode "w:i" [] ()) $-  inlinesToOpenXML opts lst-inlineToOpenXML' opts (Underline lst) =-  withTextProp (mknode "w:u" [("w:val","single")] ()) $-    inlinesToOpenXML opts lst-inlineToOpenXML' opts (Subscript lst) =-  withTextProp (mknode "w:vertAlign" [("w:val","subscript")] ())-  $ inlinesToOpenXML opts lst-inlineToOpenXML' opts (Superscript lst) =-  withTextProp (mknode "w:vertAlign" [("w:val","superscript")] ())-  $ inlinesToOpenXML opts lst-inlineToOpenXML' opts (SmallCaps lst) =-  withTextProp (mknode "w:smallCaps" [] ())-  $ inlinesToOpenXML opts lst-inlineToOpenXML' opts (Strikeout lst) =-  withTextProp (mknode "w:strike" [] ())-  $ inlinesToOpenXML opts lst-inlineToOpenXML' _ LineBreak = return [Elem br]-inlineToOpenXML' _ il@(RawInline f str)-  | f == Format "openxml" = return-                            [Text (CData CDataRaw str Nothing)]-  | otherwise             = do-      report $ InlineNotRendered il-      return []-inlineToOpenXML' opts (Quoted quoteType lst) =-  inlinesToOpenXML opts $ [Str open] ++ lst ++ [Str close]-    where (open, close) = case quoteType of-                            SingleQuote -> ("\x2018", "\x2019")-                            DoubleQuote -> ("\x201C", "\x201D")-inlineToOpenXML' opts (Math mathType str) = do-  when (mathType == DisplayMath) setFirstPara-  res <- (lift . lift) (convertMath writeOMML mathType str)-  case res of-       Right r -> return [Elem $ fromXLElement r]-       Left il -> inlineToOpenXML' opts il-inlineToOpenXML' opts (Cite _ lst) = inlinesToOpenXML opts lst-inlineToOpenXML' opts (Code attrs str) = do-  let alltoktypes = [KeywordTok ..]-  tokTypesMap <- mapM (\tt -> (,) tt <$> rStyleM (fromString $ show tt)) alltoktypes-  let unhighlighted = (map Elem . intercalate [br]) `fmap`-                       mapM formattedString (T.lines str)-      formatOpenXML _fmtOpts = intercalate [br] . map (map toHlTok)-      toHlTok (toktype,tok) =-        mknode "w:r" []-          [ mknode "w:rPr" [] $-            maybeToList (lookup toktype tokTypesMap)-            , mknode "w:t" [("xml:space","preserve")] tok ]-  withTextPropM (rStyleM "Verbatim Char")-    $ if isNothing (writerHighlightStyle opts)-          then unhighlighted-          else case highlight (writerSyntaxMap opts)-                      formatOpenXML attrs str of-                    Right h  -> return (map Elem h)-                    Left msg -> do-                      unless (T.null msg) $ report $ CouldNotHighlight msg-                      unhighlighted-inlineToOpenXML' opts (Note bs) = do-  notes <- gets stFootnotes-  notenum <- getUniqueId-  footnoteStyle <- rStyleM "Footnote Reference"-  let notemarker = mknode "w:r" []-                   [ mknode "w:rPr" [] footnoteStyle-                   , mknode "w:footnoteRef" [] () ]-  let notemarkerXml = RawInline (Format "openxml") $ ppElement notemarker-  let insertNoteRef (Plain ils : xs) = Plain (notemarkerXml : Space : ils) : xs-      insertNoteRef (Para ils  : xs) = Para  (notemarkerXml : Space : ils) : xs-      insertNoteRef xs               = Para [notemarkerXml] : xs--  contents <- local (\env -> env{ envListLevel = -1-                                , envParaProperties = mempty-                                , envTextProperties = mempty-                                , envInNote = True })-              (withParaPropM (pStyleM "Footnote Text") $-               blocksToOpenXML opts $ insertNoteRef bs)-  let newnote = mknode "w:footnote" [("w:id", notenum)] contents-  modify $ \s -> s{ stFootnotes = newnote : notes }-  return [ Elem $ mknode "w:r" []-           [ mknode "w:rPr" [] footnoteStyle-           , mknode "w:footnoteReference" [("w:id", notenum)] () ] ]--- internal link:-inlineToOpenXML' opts (Link _ txt (T.uncons -> Just ('#', xs),_)) = do-  contents <- withTextPropM (rStyleM "Hyperlink") $ inlinesToOpenXML opts txt-  return-    [ Elem $ mknode "w:hyperlink" [("w:anchor", toBookmarkName xs)] contents ]--- external link:-inlineToOpenXML' opts (Link _ txt (src,_)) = do-  contents <- withTextPropM (rStyleM "Hyperlink") $ inlinesToOpenXML opts txt-  extlinks <- gets stExternalLinks-  id' <- case M.lookup src extlinks of-            Just i   -> return i-            Nothing  -> do-              i <- ("rId" <>) <$> getUniqueId-              modify $ \st -> st{ stExternalLinks =-                        M.insert src i extlinks }-              return i-  return [ Elem $ mknode "w:hyperlink" [("r:id",id')] contents ]-inlineToOpenXML' opts (Image attr@(imgident, _, _) alt (src, title)) = do-  pageWidth <- asks envPrintWidth-  imgs <- gets stImages-  let-    stImage = M.lookup (T.unpack src) imgs-    generateImgElt (ident, _fp, mt, img) = do-      docprid <- getUniqueId-      nvpicprid <- getUniqueId-      (blipAttrs, blipContents) <--        case T.takeWhile (/=';') <$> mt of-          Just "image/svg+xml" -> do-            -- get fallback png-            mediabag <- getMediaBag-            mbFallback <--              case lookupMedia (T.unpack (src <> ".png")) mediabag of-                Just item -> do-                  id' <- T.unpack . ("rId" <>) <$> getUniqueId-                  let fp' = "media/" <> id' <> ".png"-                  let imgdata = (id',-                                 fp',-                                 Just (mediaMimeType item),-                                 BL.toStrict $ mediaContents item)-                  modify $ \st -> st { stImages =-                            M.insert fp' imgdata $ stImages st }-                  return $ Just id'-                Nothing -> return Nothing-            let extLst = mknode "a:extLst" []-                            [ mknode "a:ext"-                              [("uri","{28A0092B-C50C-407E-A947-70E740481C1C}")]-                              [ mknode "a14:useLocalDpi"-                                [("xmlns:a14","http://schemas.microsoft.com/office/drawing/2010/main"),-                                 ("val","0")] () ]-                            , mknode "a:ext"-                              [("uri","{96DAC541-7B7A-43D3-8B79-37D633B846F1}")]-                              [ mknode "asvg:svgBlip"-                                [("xmlns:asvg", "http://schemas.microsoft.com/office/drawing/2016/SVG/main"),-                                 ("r:embed",T.pack ident)] () ]-                            ]-            return (maybe [] (\id'' -> [("r:embed", T.pack id'')]) mbFallback,-                    [extLst])-          _ -> return ([("r:embed", T.pack ident)], [])-      let-        (xpt,ypt) = desiredSizeInPoints opts attr-               (either (const def) id (imageSize opts img))-        -- 12700 emu = 1 pt-        pageWidthPt = case dimension Width attr of-                        Just (Percent a) -> pageWidth * (floor $ a * 127)-                        _                -> pageWidth * 12700-        (xemu,yemu) = fitToPage (xpt * 12700, ypt * 12700) pageWidthPt-        cNvPicPr = mknode "pic:cNvPicPr" [] $-                         mknode "a:picLocks" [("noChangeArrowheads","1")-                                             ,("noChangeAspect","1")] ()-        nvPicPr  = mknode "pic:nvPicPr" []-                        [ mknode "pic:cNvPr"-                            [("descr",src)-                            ,("id", nvpicprid)-                            ,("name","Picture")] ()-                        , cNvPicPr ]-        blipFill = mknode "pic:blipFill" []-          [ mknode "a:blip" blipAttrs blipContents-          , mknode "a:stretch" [] $-              mknode "a:fillRect" [] ()-          ]-        xfrm =    mknode "a:xfrm" []-                        [ mknode "a:off" [("x","0"),("y","0")] ()-                        , mknode "a:ext" [("cx",tshow xemu)-                                         ,("cy",tshow yemu)] () ]-        prstGeom = mknode "a:prstGeom" [("prst","rect")] $-                         mknode "a:avLst" [] ()-        ln =      mknode "a:ln" [("w","9525")]-                        [ mknode "a:noFill" [] ()-                        , mknode "a:headEnd" [] ()-                        , mknode "a:tailEnd" [] () ]-        spPr =    mknode "pic:spPr" [("bwMode","auto")]-                        [xfrm, prstGeom, mknode "a:noFill" [] (), ln]-        graphic = mknode "a:graphic" [] $-          mknode "a:graphicData"-            [("uri","http://schemas.openxmlformats.org/drawingml/2006/picture")]-            [ mknode "pic:pic" []-              [ nvPicPr-              , blipFill-              , spPr-              ]-            ]-        imgElt = mknode "w:r" [] $-          mknode "w:drawing" [] $-            mknode "wp:inline" []-              [ mknode "wp:extent" [("cx",tshow xemu),("cy",tshow yemu)] ()-              , mknode "wp:effectExtent"-                [("b","0"),("l","0"),("r","0"),("t","0")] ()-              , mknode "wp:docPr"-                [ ("descr", stringify alt)-                , ("title", title)-                , ("id", docprid)-                , ("name","Picture")-                ] ()-              , graphic-              ]-      return [Elem imgElt]--  wrapBookmark imgident =<< case stImage of-    Just imgData -> generateImgElt imgData-    Nothing -> ( do --try-      (img, mt) <- P.fetchItem src-      ident <- ("rId" <>) <$> getUniqueId--      let-        imgext = case mt >>= extensionFromMimeType of-          Just x    -> "." <> x-          Nothing   -> case imageType img of-            Just Png  -> ".png"-            Just Jpeg -> ".jpeg"-            Just Gif  -> ".gif"-            Just Pdf  -> ".pdf"-            Just Eps  -> ".eps"-            Just Svg  -> ".svg"-            Just Emf  -> ".emf"-            Just Tiff -> ".tiff"-            Nothing   -> ""-        imgpath = "media/" <> ident <> imgext-        mbMimeType = mt <|> getMimeType (T.unpack imgpath)--        imgData = (T.unpack ident, T.unpack imgpath, mbMimeType, img)--      if T.null imgext-         then -- without an extension there is no rule for content type-           inlinesToOpenXML opts alt -- return alt to avoid corrupted docx-         else do-           -- insert mime type to use in constructing [Content_Types].xml-           modify $ \st -> st { stImages = M.insert (T.unpack src) imgData $ stImages st }-           generateImgElt imgData-      )-      `catchError` ( \e -> do-        report $ CouldNotFetchResource src $ T.pack (show e)-        -- emit alt text-        inlinesToOpenXML opts alt-      )--br :: Element-br = mknode "w:r" [] [mknode "w:br" [] ()]---withDirection :: PandocMonad m => WS m a -> WS m a-withDirection x = do-  isRTL <- asks envRTL-  paraProps <- asks envParaProperties-  textProps <- asks envTextProperties-  -- We want to clean all bidirection (bidi) and right-to-left (rtl)-  -- properties from the props first. This is because we don't want-  -- them to stack up.-  let paraProps' = filter (\e -> (qName . elName) e /= "bidi") (otherElements paraProps)-      textProps' = filter (\e -> (qName . elName) e /= "rtl") (otherElements textProps)-      paraStyle = styleElement paraProps-      textStyle = styleElement textProps-  if isRTL-    -- if we are going right-to-left, we (re?)add the properties.-    then flip local x $-         \env -> env { envParaProperties = EnvProps paraStyle $ mknode "w:bidi" [] () : paraProps'-                     , envTextProperties = EnvProps textStyle $ mknode "w:rtl" [] () : textProps'-                     }-    else flip local x $ \env -> env { envParaProperties = EnvProps paraStyle paraProps'-                                    , envTextProperties = EnvProps textStyle textProps'-                                    }--wrapBookmark :: (PandocMonad m) => Text -> [Content] -> WS m [Content]-wrapBookmark "" contents = return contents-wrapBookmark ident contents = do-  id' <- getUniqueId-  let bookmarkStart = mknode "w:bookmarkStart"-                       [("w:id", id')-                       ,("w:name", toBookmarkName ident)] ()-      bookmarkEnd = mknode "w:bookmarkEnd" [("w:id", id')] ()-  return $ Elem bookmarkStart : contents ++ [Elem bookmarkEnd]---- Word imposes a 40 character limit on bookmark names and requires--- that they begin with a letter.  So we just use a hash of the--- identifier when otherwise we'd have an illegal bookmark name.-toBookmarkName :: Text -> Text-toBookmarkName s-  | Just (c, _) <- T.uncons s-  , isLetter c-  , T.length s <= 40 = s-  | otherwise = T.pack $ 'X' : drop 1 (showDigest (sha1 (fromTextLazy $ TL.fromStrict s)))+import Control.Monad (MonadPlus(mplus), foldM)+import Control.Monad.Except (throwError)+import Control.Monad.Reader ( ReaderT(runReaderT) )+import Control.Monad.State.Strict ( StateT(runStateT) )+import qualified Data.ByteString.Lazy as BL+import Data.Containers.ListUtils (nubOrd)+import Data.Char (isSpace)+import Data.List (isPrefixOf, isSuffixOf)+import Data.String (fromString)+import qualified Data.Map as M+import Data.Maybe (fromMaybe, mapMaybe, maybeToList)+import qualified Data.Set as Set+import qualified Data.Text as T+import Data.Text (Text)+import Data.Time.Clock.POSIX+import Skylighting+import Text.Pandoc.Class (PandocMonad, toLang)+import qualified Text.Pandoc.Class.PandocMonad as P+import Text.Pandoc.Data (readDataFile, readDefaultDataFile)+import Data.Time+import qualified Text.Pandoc.UTF8 as UTF8+import Text.Pandoc.Definition+import Text.Pandoc.Error+import Text.Pandoc.MIME (getMimeTypeDef)+import Text.Pandoc.Options+import Text.Pandoc.Readers.Docx.Parse (extractTarget)+import Text.Pandoc.Writers.Docx.StyleMap+import Text.Pandoc.Writers.Docx.Types+import Text.Pandoc.Writers.Docx.OpenXML (writeOpenXML, maxListLevel)+import Text.Pandoc.Shared+import Text.Pandoc.Walk+import Text.Pandoc.Writers.Shared+import Text.Pandoc.Writers.OOXML+import Text.Pandoc.XML.Light as XML+import Data.Generics (mkT, everywhere)+import Text.Collate.Lang (renderLang, Lang(..))++renumIdMap :: Int -> [Element] -> M.Map Text Text+renumIdMap _ [] = M.empty+renumIdMap n (e:es)+  | Just oldId <- findAttr (QName "Id" Nothing Nothing) e =+      M.insert oldId ("rId" <> tshow n) (renumIdMap (n+1) es)+  | otherwise = renumIdMap n es++replaceAttr :: (QName -> Bool) -> Text -> [XML.Attr] -> [XML.Attr]+replaceAttr f val = map $+    \a -> if f (attrKey a) then XML.Attr (attrKey a) val else a++renumId :: (QName -> Bool) -> M.Map Text Text -> Element -> Element+renumId f renumMap e+  | Just oldId <- findAttrBy f e+  , Just newId <- M.lookup oldId renumMap =+    let attrs' = replaceAttr f newId (elAttribs e)+    in+     e { elAttribs = attrs' }+  | otherwise = e++renumIds :: (QName -> Bool) -> M.Map Text Text -> [Element] -> [Element]+renumIds f renumMap = map (renumId f renumMap)++writeDocx :: (PandocMonad m)+          => WriterOptions  -- ^ Writer options+          -> Pandoc         -- ^ Document to convert+          -> m BL.ByteString+writeDocx opts doc = do+  let Pandoc meta blocks = walk fixDisplayMath doc+  setupTranslations meta+  let blocks' = makeSections True Nothing blocks+  let doc' = Pandoc meta blocks'++  username <- P.lookupEnv "USERNAME"+  utctime <- P.getTimestamp+  oldUserDataDir <- P.getUserDataDir+  P.setUserDataDir Nothing+  res <- readDefaultDataFile "reference.docx"+  P.setUserDataDir oldUserDataDir+  let distArchive = toArchive $ BL.fromStrict res+  refArchive <- case writerReferenceDoc opts of+                     Just f  -> toArchive . BL.fromStrict . fst+                                   <$> P.fetchItem (T.pack f)+                     Nothing -> toArchive . BL.fromStrict <$>+                          readDataFile "reference.docx"++  parsedDoc <- parseXml refArchive distArchive "word/document.xml"+  let wname f qn = qPrefix qn == Just "w" && f (qName qn)+  let mbsectpr = filterElementName (wname (=="sectPr")) parsedDoc++  -- Gets the template size+  let mbpgsz = mbsectpr >>= filterElementName (wname (=="pgSz"))+  let mbAttrSzWidth = mbpgsz >>= lookupAttrBy ((=="w") . qName) . elAttribs++  let mbpgmar = mbsectpr >>= filterElementName (wname (=="pgMar"))+  let mbAttrMarLeft = mbpgmar >>= lookupAttrBy ((=="left") . qName) . elAttribs+  let mbAttrMarRight = mbpgmar >>= lookupAttrBy ((=="right") . qName) . elAttribs++  -- Get the available area (converting the size and the margins to int and+  -- doing the difference+  let pgContentWidth = do+                         w <- mbAttrSzWidth >>= safeRead+                         r <- mbAttrMarRight >>= safeRead+                         l <- mbAttrMarLeft >>= safeRead+                         pure $ w - r - l++  -- styles+  mblang <- toLang $ getLang opts meta+  -- TODO FIXME avoid this generic traversal!+  -- lang is in w:docDefaults /  w:rPr  /  w:lang+  let addLang :: Element -> Element+      addLang = case mblang of+                  Nothing -> id+                  Just l  -> everywhere (mkT (go l))+        where+          go :: Lang -> Element -> Element+          go lang e'+           | qName (elName e') == "lang"+             = if isEastAsianLang lang+                  then e'{ elAttribs =+                             map (setattr "eastAsia" (renderLang lang)) $+                             elAttribs e' }+                  else+                    if isBidiLang lang+                       then e'{ elAttribs =+                                 map (setattr "bidi" (renderLang lang)) $+                                 elAttribs e' }+                       else e'{ elAttribs =+                                 map (setattr "val" (renderLang lang)) $+                                 elAttribs e' }+           | otherwise = e'++          setattr attrname l (XML.Attr qn@(QName s _ _) _)+            | s == attrname  = XML.Attr qn l+          setattr _ _ x      = x++          isEastAsianLang Lang{ langLanguage = lang } =+             lang == "zh" || lang == "jp" || lang == "ko"+          isBidiLang Lang{ langLanguage = lang } =+             lang == "he" || lang == "ar"++  let stylepath = "word/styles.xml"+  styledoc <- addLang <$> parseXml refArchive distArchive stylepath++  -- parse styledoc for heading styles+  let styleMaps = getStyleMaps refArchive++  let tocTitle = case lookupMetaInlines "toc-title" meta of+                   [] -> stTocTitle defaultWriterState+                   ls -> ls++  let initialSt = defaultWriterState {+          stStyleMaps  = styleMaps+        , stTocTitle   = tocTitle+        , stCurId      = 20+        }++  let isRTLmeta = case lookupMeta "dir" meta of+        Just (MetaString "rtl")        -> True+        Just (MetaInlines [Str "rtl"]) -> True+        _                              -> False++  let env = defaultWriterEnv {+          envRTL = isRTLmeta+        , envChangesAuthor = fromMaybe "unknown" username+        , envChangesDate   = T.pack $ formatTime defaultTimeLocale "%FT%XZ" utctime+        , envPrintWidth = maybe 420 (`quot` 20) pgContentWidth+        }++  parsedRels <- parseXml refArchive distArchive "word/_rels/document.xml.rels"+  let isHeaderNode e = findAttr (QName "Type" Nothing Nothing) e == Just "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header"+  let isFooterNode e = findAttr (QName "Type" Nothing Nothing) e == Just "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer"+  let headers = filterElements isHeaderNode parsedRels+  let footers = filterElements isFooterNode parsedRels+  -- word/_rels/document.xml.rels+  let toBaseRel (url', id', target') = mknode "Relationship"+                                          [("Type",url')+                                          ,("Id",id')+                                          ,("Target",target')] ()+  let baserels' = map toBaseRel+                    [("http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",+                      "rId1",+                      "numbering.xml")+                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",+                      "rId2",+                      "styles.xml")+                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",+                      "rId3",+                      "settings.xml")+                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings",+                      "rId4",+                      "webSettings.xml")+                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",+                      "rId5",+                      "fontTable.xml")+                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",+                      "rId6",+                      "theme/theme1.xml")+                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",+                      "rId7",+                      "footnotes.xml")+                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",+                      "rId8",+                      "comments.xml")+                    ]++  let idMap = renumIdMap (length baserels' + 1) (headers ++ footers)++  -- adjust contents to add sectPr from reference.docx+  let sectpr = case mbsectpr of+        Just sectpr' -> let cs = renumIds+                                 (\q -> qName q == "id" && qPrefix q == Just "r")+                                 idMap+                                 (elChildren sectpr')+                        in Just . ppElement $+                             add_attrs (elAttribs sectpr') $ mknode "w:sectPr" [] cs+        Nothing      -> Nothing+++  ((contents, footnotes, comments), st) <- runStateT+                         (runReaderT+                          (writeOpenXML opts{ writerWrapText = WrapNone+                                            , writerVariables =+                                                (maybe id (setField "sectpr") sectpr)+                                                (writerVariables opts)+                                                }+                                        doc')+                          env)+                         initialSt+  let epochtime = floor $ utcTimeToPOSIXSeconds utctime+  let imgs = M.elems $ stImages st++  -- create entries for images in word/media/...+  let toImageEntry (_,path,_,img) = toEntry ("word/" ++ path) epochtime $ toLazy img+  let imageEntries = map toImageEntry imgs++  let stdAttributes =+            [("xmlns:w","http://schemas.openxmlformats.org/wordprocessingml/2006/main")+            ,("xmlns:m","http://schemas.openxmlformats.org/officeDocument/2006/math")+            ,("xmlns:r","http://schemas.openxmlformats.org/officeDocument/2006/relationships")+            ,("xmlns:o","urn:schemas-microsoft-com:office:office")+            ,("xmlns:v","urn:schemas-microsoft-com:vml")+            ,("xmlns:w10","urn:schemas-microsoft-com:office:word")+            ,("xmlns:a","http://schemas.openxmlformats.org/drawingml/2006/main")+            ,("xmlns:pic","http://schemas.openxmlformats.org/drawingml/2006/picture")+            ,("xmlns:wp","http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing")]+++ -- we create [Content_Types].xml and word/_rels/document.xml.rels+  -- from scratch rather than reading from reference.docx,+  -- because Word sometimes changes these files when a reference.docx is modified,+  -- e.g. deleting the reference to footnotes.xml or removing default entries+  -- for image content types.++  -- [Content_Types].xml+  let mkOverrideNode (part', contentType') = mknode "Override"+               [("PartName", T.pack part')+               ,("ContentType", contentType')] ()+  let mkImageOverride (_, imgpath, mbMimeType, _) =+          mkOverrideNode ("/word/" <> imgpath,+                          fromMaybe "application/octet-stream" mbMimeType)+  let mkMediaOverride imgpath =+          mkOverrideNode ("/" <> imgpath, getMimeTypeDef imgpath)+  let overrides = map mkOverrideNode (+                  [("/word/webSettings.xml",+                    "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml")+                  ,("/word/numbering.xml",+                    "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml")+                  ,("/word/settings.xml",+                    "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml")+                  ,("/word/theme/theme1.xml",+                    "application/vnd.openxmlformats-officedocument.theme+xml")+                  ,("/word/fontTable.xml",+                    "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml")+                  ,("/docProps/app.xml",+                    "application/vnd.openxmlformats-officedocument.extended-properties+xml")+                  ,("/docProps/core.xml",+                    "application/vnd.openxmlformats-package.core-properties+xml")+                  ,("/docProps/custom.xml",+                    "application/vnd.openxmlformats-officedocument.custom-properties+xml")+                  ,("/word/styles.xml",+                    "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml")+                  ,("/word/document.xml",+                    "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml")+                  ,("/word/comments.xml",+                    "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml")+                  ,("/word/footnotes.xml",+                    "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml")+                  ] +++                  map (\x -> (maybe "" (T.unpack . ("/word/" <>)) (extractTarget x),+                       "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml")) headers +++                  map (\x -> (maybe "" (T.unpack . ("/word/" <>)) (extractTarget x),+                       "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml")) footers) +++                    map mkImageOverride imgs +++                    [ mkMediaOverride (eRelativePath e)+                        | e <- zEntries refArchive+                        , "word/media/" `isPrefixOf` eRelativePath e ]++  let mkDefaultNode (ext, mt) =+        mknode "Default" [("Extension",ext),("ContentType",mt)] ()+  let defaultnodes = map mkDefaultNode+        [("xml", "application/xml"),+         ("rels", "application/vnd.openxmlformats-package.relationships+xml"),+         ("odttf",+           "application/vnd.openxmlformats-officedocument.obfuscatedFont")]+  let contentTypesDoc = mknode "Types" [("xmlns","http://schemas.openxmlformats.org/package/2006/content-types")] $ defaultnodes ++ overrides+  let contentTypesEntry = toEntry "[Content_Types].xml" epochtime+        $ renderXml contentTypesDoc+++  let renumHeaders = renumIds (\q -> qName q == "Id") idMap headers+  let renumFooters = renumIds (\q -> qName q == "Id") idMap footers+  let baserels = baserels' ++ renumHeaders ++ renumFooters+  let toImgRel (ident,path,_,_) =  mknode "Relationship" [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"),("Id",T.pack ident),("Target",T.pack path)] ()+  let imgrels = map toImgRel imgs+  let toLinkRel (src,ident) =  mknode "Relationship" [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"),("Id",ident),("Target",src),("TargetMode","External") ] ()+  let linkrels = map toLinkRel $ M.toList $ stExternalLinks st+  let reldoc = mknode "Relationships" [("xmlns","http://schemas.openxmlformats.org/package/2006/relationships")] $ baserels ++ imgrels ++ linkrels+  let relEntry = toEntry "word/_rels/document.xml.rels" epochtime+        $ renderXml reldoc++  -- let sectpr = fromMaybe (mknode "w:sectPr" [] ()) mbsectpr'+  let contents' = BL.fromStrict $ UTF8.fromText contents++  -- word/document.xml+  let contentEntry = toEntry "word/document.xml" epochtime contents'++  -- footnotes+  let notes = mknode "w:footnotes" stdAttributes footnotes+  let footnotesEntry = toEntry "word/footnotes.xml" epochtime $ renderXml notes++  -- footnote rels+  let footnoteRelEntry = toEntry "word/_rels/footnotes.xml.rels" epochtime+        $ renderXml $ mknode "Relationships" [("xmlns","http://schemas.openxmlformats.org/package/2006/relationships")]+        linkrels++  -- comments+  let commentsEntry = toEntry "word/comments.xml" epochtime+        $ renderXml $ mknode "w:comments" stdAttributes comments++  -- styles++  -- We only want to inject paragraph and text properties that+  -- are not already in the style map. Note that keys in the stylemap+  -- are normalized as lowercase.+  let newDynamicParaProps = filter+        (\sty -> not $ hasStyleName sty $ smParaStyle styleMaps)+        (Set.toList $ stDynamicParaProps st)++      newDynamicTextProps = filter+        (\sty -> not $ hasStyleName sty $ smCharStyle styleMaps)+        (Set.toList $ stDynamicTextProps st)++  let newstyles = map newParaPropToOpenXml newDynamicParaProps +++                  map newTextPropToOpenXml newDynamicTextProps +++                  maybe [] (styleToOpenXml styleMaps) (writerHighlightStyle opts)+  let styledoc' = styledoc{ elContent = elContent styledoc +++                                           map Elem newstyles }+  let styleEntry = toEntry stylepath epochtime $ renderXml styledoc'++  -- construct word/numbering.xml+  let numpath = "word/numbering.xml"+  numbering <- parseXml refArchive distArchive numpath+  let newNumElts = mkNumbering (stLists st)+  let pandocAdded e =+       case findAttrBy ((== "abstractNumId") . qName) e >>= safeRead of+         Just numid -> numid >= (990 :: Int)+         Nothing    ->+           case findAttrBy ((== "numId") . qName) e >>= safeRead of+             Just numid -> numid >= (1000 :: Int)+             Nothing    -> False+  let oldElts = filter (not . pandocAdded) $ onlyElems (elContent numbering)+  let allElts = oldElts ++ newNumElts+  let numEntry = toEntry numpath epochtime $ renderXml numbering{ elContent =+                       -- we want all the abstractNums first, then the nums,+                       -- otherwise things break:+                       [Elem e | e <- allElts+                               , qName (elName e) == "abstractNum" ] +++                       [Elem e | e <- allElts+                               , qName (elName e) == "num" ] }++  let keywords = case lookupMeta "keywords" meta of+                       Just (MetaList xs) -> map stringify xs+                       _                  -> []++  -- docProps/core.xml+  let docPropsPath = "docProps/core.xml"+  let extraCoreProps = ["subject","lang","category","description"]+  let extraCorePropsMap = M.fromList $ zip extraCoreProps+                       ["dc:subject","dc:language","cp:category","dc:description"]+  let lookupMetaString' :: Text -> Meta -> Text+      lookupMetaString' key' meta' =+        case key' of+             "description"    -> T.intercalate "_x000d_\n" (map stringify $ lookupMetaBlocks "description" meta')+             key''            -> lookupMetaString key'' meta'++  let docProps = mknode "cp:coreProperties"+          [("xmlns:cp","http://schemas.openxmlformats.org/package/2006/metadata/core-properties")+          ,("xmlns:dc","http://purl.org/dc/elements/1.1/")+          ,("xmlns:dcterms","http://purl.org/dc/terms/")+          ,("xmlns:dcmitype","http://purl.org/dc/dcmitype/")+          ,("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance")]+          $ mktnode "dc:title" [] (stringify $ docTitle meta)+          : mktnode "dc:creator" [] (T.intercalate "; " (map stringify $ docAuthors meta))+          : [ mktnode (M.findWithDefault "" k extraCorePropsMap) [] (lookupMetaString' k meta)+            | k <- M.keys (unMeta meta), k `elem` extraCoreProps]+          ++ mknode "cp:keywords" [] (T.intercalate ", " keywords)+          : (\x -> [ mknode "dcterms:created" [("xsi:type","dcterms:W3CDTF")] x+                   , mknode "dcterms:modified" [("xsi:type","dcterms:W3CDTF")] x+                   ]) (T.pack $ formatTime defaultTimeLocale "%FT%XZ" utctime)+  let docPropsEntry = toEntry docPropsPath epochtime $ renderXml docProps++  -- docProps/custom.xml+  let customProperties :: [(Text, Text)]+      customProperties = [ (k, lookupMetaString k meta)+                         | k <- M.keys (unMeta meta)+                         , k `notElem` (["title", "author", "keywords"]+                                       ++ extraCoreProps)]+  let mkCustomProp (k, v) pid = mknode "property"+         [("fmtid","{D5CDD505-2E9C-101B-9397-08002B2CF9AE}")+         ,("pid", tshow pid)+         ,("name", k)] $ mknode "vt:lpwstr" [] v+  let customPropsPath = "docProps/custom.xml"+  let customProps = mknode "Properties"+          [("xmlns","http://schemas.openxmlformats.org/officeDocument/2006/custom-properties")+          ,("xmlns:vt","http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes")+          ] $ zipWith mkCustomProp customProperties [(2 :: Int)..]+  let customPropsEntry = toEntry customPropsPath epochtime $ renderXml customProps++  let relsPath = "_rels/.rels"+  let rels = mknode "Relationships" [("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships")]+        $ map (\attrs -> mknode "Relationship" attrs ())+        [ [("Id","rId1")+          ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument")+          ,("Target","word/document.xml")]+        , [("Id","rId4")+          ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties")+          ,("Target","docProps/app.xml")]+        , [("Id","rId3")+          ,("Type","http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties")+          ,("Target","docProps/core.xml")]+        , [("Id","rId5")+          ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties")+          ,("Target","docProps/custom.xml")]+        ]+  let relsEntry = toEntry relsPath epochtime $ renderXml rels++  -- we use dist archive for settings.xml, because Word sometimes+  -- adds references to footnotes or endnotes we don't have...+  -- we do, however, copy some settings over from reference+  let settingsPath = "word/settings.xml"++  settingsEntry <- copyChildren refArchive distArchive settingsPath epochtime+                      -- note: these must go in the following order:+                     [ "writeProtection"+                     , "view"+                     , "zoom"+                     , "removePersonalInformation"+                     , "removeDateAndTime"+                     , "doNotDisplayPageBoundaries"+                     , "displayBackgroundShape"+                     , "printPostScriptOverText"+                     , "printFractionalCharacterWidth"+                     , "printFormsData"+                     , "embedTrueTypeFonts"+                     , "embedSystemFonts"+                     , "saveSubsetFonts"+                     , "saveFormsData"+                     , "mirrorMargins"+                     , "alignBordersAndEdges"+                     , "bordersDoNotSurroundHeader"+                     , "bordersDoNotSurroundFooter"+                     , "gutterAtTop"+                     , "hideSpellingErrors"+                     , "hideGrammaticalErrors"+                     , "activeWritingStyle"+                     , "proofState"+                     , "formsDesign"+                     , "attachedTemplate"+                     , "linkStyles"+                     , "stylePaneFormatFilter"+                     , "stylePaneSortMethod"+                     , "documentType"+                     , "mailMerge"+                     , "revisionView"+                     , "trackRevisions"+                     , "doNotTrackMoves"+                     , "doNotTrackFormatting"+                     , "documentProtection"+                     , "autoFormatOverride"+                     , "styleLockTheme"+                     , "styleLockQFSet"+                     , "defaultTabStop"+                     , "autoHyphenation"+                     , "consecutiveHyphenLimit"+                     , "hyphenationZone"+                     , "doNotHyphenateCaps"+                     , "showEnvelope"+                     , "summaryLength"+                     , "clickAndTypeStyle"+                     , "defaultTableStyle"+                     , "evenAndOddHeaders"+                     , "bookFoldRevPrinting"+                     , "bookFoldPrinting"+                     , "bookFoldPrintingSheets"+                     , "drawingGridHorizontalSpacing"+                     , "drawingGridVerticalSpacing"+                     , "displayHorizontalDrawingGridEvery"+                     , "displayVerticalDrawingGridEvery"+                     , "doNotUseMarginsForDrawingGridOrigin"+                     , "drawingGridHorizontalOrigin"+                     , "drawingGridVerticalOrigin"+                     , "doNotShadeFormData"+                     , "noPunctuationKerning"+                     , "characterSpacingControl"+                     , "printTwoOnOne"+                     , "strictFirstAndLastChars"+                     , "noLineBreaksAfter"+                     , "noLineBreaksBefore"+                     , "savePreviewPicture"+                     , "doNotValidateAgainstSchema"+                     , "saveInvalidXml"+                     , "ignoreMixedContent"+                     , "alwaysShowPlaceholderText"+                     , "doNotDemarcateInvalidXml"+                     , "saveXmlDataOnly"+                     , "useXSLTWhenSaving"+                     , "saveThroughXslt"+                     , "showXMLTags"+                     , "alwaysMergeEmptyNamespace"+                     , "updateFields"+                     , "hdrShapeDefaults"+                     -- , "footnotePr" -- this can cause problems, see #9522+                     -- , "endnotePr"+                     , "compat"+                     , "docVars"+                     , "rsids"+                     , "attachedSchema"+                     , "themeFontLang"+                     , "clrSchemeMapping"+                     , "doNotIncludeSubdocsInStats"+                     , "doNotAutoCompressPictures"+                     , "forceUpgrade"+                     , "captions"+                     , "readModeInkLockDown"+                     , "smartTagType"+                     , "shapeDefaults"+                     , "doNotEmbedSmartTags"+                     , "decimalSymbol"+                     , "listSeparator" ]++  let entryFromArchive arch path =+         maybe (throwError $ PandocSomeError+                           $ T.pack $ path ++ " missing in reference docx")+               return+               (findEntryByPath path arch `mplus` findEntryByPath path distArchive)+  docPropsAppEntry <- entryFromArchive refArchive "docProps/app.xml"+  themeEntry <- entryFromArchive refArchive "word/theme/theme1.xml"+  fontTableEntry <- entryFromArchive refArchive "word/fontTable.xml"+  let fontTableRelsEntries = maybeToList $+       findEntryByPath "word/_rels/fontTable.xml.rels" refArchive+  let fontEntries = [entry | entry <- zEntries refArchive+                           , "word/fonts/" `isPrefixOf` (eRelativePath entry)]+                        -- or parse fontTable.xml.rels?+  webSettingsEntry <- entryFromArchive refArchive "word/webSettings.xml"+  headerFooterEntries <- mapM (entryFromArchive refArchive . ("word/" ++)) $+                         mapMaybe (fmap T.unpack . extractTarget)+                         (headers ++ footers)+  let miscRelEntries = [ e | e <- zEntries refArchive+                       , "word/_rels/" `isPrefixOf` eRelativePath e+                       , ".xml.rels" `isSuffixOf` eRelativePath e+                       , eRelativePath e /= "word/_rels/document.xml.rels"+                       , eRelativePath e /= "word/_rels/footnotes.xml.rels" ]+  let otherMediaEntries = [ e | e <- zEntries refArchive+                          , "word/media/" `isPrefixOf` eRelativePath e ]++  -- Create archive+  let archive = foldr addEntryToArchive emptyArchive $+                  contentTypesEntry : relsEntry : contentEntry : relEntry :+                  footnoteRelEntry : numEntry : styleEntry : footnotesEntry :+                  commentsEntry :+                  docPropsEntry : docPropsAppEntry : customPropsEntry :+                  themeEntry :+                  settingsEntry : webSettingsEntry :+                  fontTableEntry :+                  fontTableRelsEntries ++ fontEntries +++                  imageEntries ++ headerFooterEntries +++                  miscRelEntries ++ otherMediaEntries+  return $ fromArchive archive++newParaPropToOpenXml :: ParaStyleName -> Element+newParaPropToOpenXml (fromStyleName -> s) =+  let styleId = T.filter (not . isSpace) s+  in mknode "w:style" [ ("w:type", "paragraph")+                      , ("w:customStyle", "1")+                      , ("w:styleId", styleId)]+     [ mknode "w:name" [("w:val", s)] ()+     , mknode "w:basedOn" [("w:val","BodyText")] ()+     , mknode "w:qFormat" [] ()+     ]++newTextPropToOpenXml :: CharStyleName -> Element+newTextPropToOpenXml (fromStyleName -> s) =+  let styleId = T.filter (not . isSpace) s+  in mknode "w:style" [ ("w:type", "character")+                      , ("w:customStyle", "1")+                      , ("w:styleId", styleId)]+     [ mknode "w:name" [("w:val", s)] ()+     , mknode "w:basedOn" [("w:val","BodyTextChar")] ()+     ]++styleToOpenXml :: StyleMaps -> Style -> [Element]+styleToOpenXml sm style =+  maybeToList parStyle ++ mapMaybe toStyle alltoktypes+  where alltoktypes = enumFromTo KeywordTok NormalTok+        toStyle toktype | hasStyleName (fromString $ show toktype) (smCharStyle sm) = Nothing+                        | otherwise = Just $+                          mknode "w:style" [("w:type","character"),+                           ("w:customStyle","1"),("w:styleId", tshow toktype)]+                             [ mknode "w:name" [("w:val", tshow toktype)] ()+                             , mknode "w:basedOn" [("w:val","VerbatimChar")] ()+                             , mknode "w:rPr" [] $+                               [ mknode "w:b" [] () | tokFeature tokenBold toktype ] +++                               [ mknode "w:i" [] () | tokFeature tokenItalic toktype ] +++                               [ mknode "w:color" [("w:val", tokCol toktype)] ()+                                 | tokCol toktype /= "auto" ] +++                               [ mknode "w:u" [] () | tokFeature tokenUnderline toktype ] +++                               [ mknode "w:shd" [("w:val","clear")+                                                ,("w:fill",tokBg toktype)] ()+                                 | tokBg toktype /= "auto" ]+                             ]+        tokStyles = tokenStyles style+        tokFeature f toktype = maybe False f $ M.lookup toktype tokStyles+        tokCol toktype = maybe "auto" (T.pack . drop 1 . fromColor)+                         $ (tokenColor =<< M.lookup toktype tokStyles)+                           `mplus` defaultColor style+        tokBg toktype = maybe "auto" (T.pack . drop 1 . fromColor)+                         $ (tokenBackground =<< M.lookup toktype tokStyles)+                           `mplus` backgroundColor style+        parStyle | hasStyleName "Source Code" (smParaStyle sm) = Nothing+                 | otherwise = Just $+                   mknode "w:style" [("w:type","paragraph"),+                           ("w:customStyle","1"),("w:styleId","SourceCode")]+                             [ mknode "w:name" [("w:val","Source Code")] ()+                             , mknode "w:basedOn" [("w:val","Normal")] ()+                             , mknode "w:link" [("w:val","VerbatimChar")] ()+                             , mknode "w:pPr" []+                               $ mknode "w:wordWrap" [("w:val","off")] ()+                               :+                         maybe [] (\col -> [mknode "w:shd" [("w:val","clear"),("w:fill", T.pack $ drop 1 $ fromColor col)] ()]) (backgroundColor style)+                             ]++copyChildren :: (PandocMonad m)+             => Archive -> Archive -> String -> Integer -> [Text] -> m Entry+copyChildren refArchive distArchive path timestamp elNames = do+  ref  <- parseXml refArchive distArchive path+  dist <- parseXml distArchive distArchive path+  els <- foldM (addEl ref dist) [] (reverse elNames)+  return $ toEntry path timestamp+         $ renderXml dist{ elContent = map cleanElem els }+  where+    addEl ref dist els name =+      case filterChildName (hasName name) ref `mplus`+             filterChildName (hasName name) dist of+        Just el -> pure (el : els)+        Nothing -> pure els+    hasName name = (== name) . qName+    cleanElem el@Element{elName=name} = Elem el{elName=name{qURI=Nothing}}++-- this is the lowest number used for a list numId+baseListId :: Int+baseListId = 1000++mkNumbering :: [ListMarker] -> [Element]+mkNumbering lists =+  elts ++ zipWith mkNum lists [baseListId..(baseListId + length lists - 1)]+    where elts = map mkAbstractNum (nubOrd lists)++mkNum :: ListMarker -> Int -> Element+mkNum marker numid =+  mknode "w:num" [("w:numId",tshow numid)]+   $ mknode "w:abstractNumId" [("w:val",listMarkerToId marker)] ()+   : case marker of+       NoMarker     -> []+       BulletMarker -> []+       CheckboxMarker _ -> []+       NumberMarker _ _ start ->+          map (\lvl -> mknode "w:lvlOverride" [("w:ilvl",tshow (lvl :: Int))]+              $ mknode "w:startOverride" [("w:val",tshow start)] ())+                [0..maxListLevel]++mkAbstractNum :: ListMarker -> Element+mkAbstractNum marker =+  mknode "w:abstractNum" [("w:abstractNumId",listMarkerToId marker)]+    $ mknode "w:nsid" [("w:val", T.justifyRight 8 '0' ("A" <> listMarkerToId marker))] ()+    : mknode "w:multiLevelType" [("w:val","multilevel")] ()+    : map (mkLvl marker)+      [0..maxListLevel]++mkLvl :: ListMarker -> Int -> Element+mkLvl marker lvl =+  mknode "w:lvl" [("w:ilvl",tshow lvl)] $+    (case marker of+        NumberMarker{} -> [mknode "w:start" [("w:val",start)] ()]+        _ -> []) +++    [ mknode "w:numFmt" [("w:val",fmt)] ()+    , mknode "w:lvlText" [("w:val", lvltxt)] ()+    , mknode "w:lvlJc" [("w:val","left")] ()+    , mknode "w:pPr" [] $+        mknode "w:ind" [ ("w:left",tshow $ lvl * step + step)+                       , ("w:hanging",tshow hang)+                       ] ()+    ] +++    maybe [] (\font ->+                [ mknode "w:rPr" []+                  [ mknode "w:rFonts" [ ("w:ascii", font)+                                      , ("w:hAnsi", font)+                                      , ("w:cs", font)+                                      , ("w:hint", "default") ] () ]]) mbfont+    where (fmt, lvltxt, mbfont, start) =+            case marker of+                 NoMarker             -> ("bullet"," ", Nothing, "1")+                 BulletMarker         -> bulletFor lvl+                 CheckboxMarker False -> ("bullet","\9744", Nothing, "1")+                 CheckboxMarker True  -> ("bullet","\9746", Nothing, "1")+                 NumberMarker st de n -> (styleFor st lvl+                                         ,patternFor de ("%" <> tshow (lvl + 1))+                                         ,Nothing+                                         ,tshow n)+          step = 720+          hang :: Int+          hang = 360+          bulletFor 0 = ("bullet", "\xf0b7", Just "Symbol", "1") -- filled circle+          bulletFor 1 = ("bullet", "o", Just "Courier New", "1") -- open o+          bulletFor 2 = ("bullet", "\xf0a7", Just "Wingdings", "1")  -- closed box+          bulletFor x = bulletFor (x `mod` 3)+          styleFor UpperAlpha _   = "upperLetter"+          styleFor LowerAlpha _   = "lowerLetter"+          styleFor UpperRoman _   = "upperRoman"+          styleFor LowerRoman _   = "lowerRoman"+          styleFor Decimal _      = "decimal"+          styleFor DefaultStyle 0 = "decimal"+          styleFor DefaultStyle 1 = "lowerLetter"+          styleFor DefaultStyle 2 = "lowerRoman"+          styleFor DefaultStyle 3 = "decimal"+          styleFor DefaultStyle 4 = "lowerLetter"+          styleFor DefaultStyle 5 = "lowerRoman"+          styleFor DefaultStyle x = styleFor DefaultStyle (x `mod` 6)+          styleFor _ _            = "decimal"+          patternFor OneParen s  = s <> ")"+          patternFor TwoParens s = "(" <> s <> ")"+          patternFor _ s         = s <> "."
+ src/Text/Pandoc/Writers/Docx/OpenXML.hs view
@@ -0,0 +1,1034 @@+{-# LANGUAGE PatternGuards       #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections       #-}+{-# LANGUAGE ViewPatterns        #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE LambdaCase          #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE TypeApplications    #-}+{- |+   Module      : Text.Pandoc.Writers.Docx+   Copyright   : Copyright (C) 2012-2024 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++Conversion of 'Pandoc' documents to docx.+-}+module Text.Pandoc.Writers.Docx.OpenXML ( writeOpenXML, maxListLevel ) where++import Control.Monad (when, unless)+import Control.Applicative ((<|>))+import Control.Monad.Except (catchError)+import qualified Data.ByteString.Lazy as BL+import Data.Char (isLetter, isSpace)+import Data.Bifunctor (first)+import Text.Pandoc.Char (isCJK)+import Data.Ord (comparing)+import Data.String (fromString)+import qualified Data.Map as M+import Data.Maybe (fromMaybe, isNothing, maybeToList, isJust)+import Control.Monad.State ( gets, modify, MonadTrans(lift) )+import Control.Monad.Reader ( asks, MonadReader(local) )+import qualified Data.Set as Set+import qualified Data.Text as T+import Data.Text (Text)+import qualified Data.Text.Lazy as TL+import Data.Digest.Pure.SHA (sha1, showDigest)+import Skylighting+import Text.DocLayout (hcat, vcat, literal, render)+import Text.Pandoc.Class (PandocMonad, report, getMediaBag)+import Text.Pandoc.Translations (Term(Abstract), translateTerm)+import Text.Pandoc.MediaBag (lookupMedia, MediaItem(..))+import qualified Text.Pandoc.Translations as Term+import qualified Text.Pandoc.Class.PandocMonad as P+import Text.Pandoc.UTF8 (fromTextLazy)+import Text.Pandoc.Definition+import Text.Pandoc.Highlighting (highlight)+import Text.Pandoc.Templates (compileDefaultTemplate, renderTemplate)+import Text.Pandoc.ImageSize+import Text.Pandoc.Logging+import Text.Pandoc.MIME (extensionFromMimeType, getMimeType)+import Text.Pandoc.Options+import Text.Pandoc.Writers.Docx.StyleMap+import Text.Pandoc.Writers.Docx.Table as Table+import Text.Pandoc.Writers.Docx.Types+import Text.Pandoc.Shared+import Text.Pandoc.Walk+import qualified Text.Pandoc.Writers.GridTable as Grid+import Text.Pandoc.Writers.Math+import Text.Pandoc.Writers.Shared+import Text.TeXMath+import Text.Pandoc.Writers.OOXML+import Text.Pandoc.XML.Light as XML+import Data.List (sortBy, intercalate, groupBy)++-- from wml.xsd EG_RPrBase+rPrTagOrder :: M.Map Text Int+rPrTagOrder =+  M.fromList+  (zip [ "rStyle"+    , "rFonts"+    , "b"+    , "bCs"+    , "i"+    , "iCs"+    , "caps"+    , "smallCaps"+    , "strike"+    , "dstrike"+    , "outline"+    , "shadow"+    , "emboss"+    , "imprint"+    , "noProof"+    , "snapToGrid"+    , "vanish"+    , "webHidden"+    , "color"+    , "spacing"+    , "w"+    , "kern"+    , "position"+    , "sz"+    , "szCs"+    , "highlight"+    , "u"+    , "effect"+    , "bdr"+    , "shd"+    , "fitText"+    , "vertAlign"+    , "rtl"+    , "cs"+    , "em"+    , "lang"+    , "eastAsianLayout"+    , "specVanish"+    , "oMath"+    ] [0..])++sortSquashed :: [Element] -> [Element]+sortSquashed l =+  sortBy (comparing tagIndex) l+  where+    tagIndex :: Element -> Int+    tagIndex el =+      fromMaybe 0 (M.lookup tag rPrTagOrder)+      where tag = (qName . elName) el++squashProps :: EnvProps -> [Element]+squashProps (EnvProps Nothing es) = sortSquashed es+squashProps (EnvProps (Just e) es) = sortSquashed (e : es)++-- | Certain characters are invalid in XML even if escaped.+-- See #1992+stripInvalidChars :: Text -> Text+stripInvalidChars = T.filter isValidChar++-- | See XML reference+isValidChar :: Char -> Bool+isValidChar '\t' = True+isValidChar '\n' = True+isValidChar '\r' = True+isValidChar '\xFFFE' = False+isValidChar '\xFFFF' = False+isValidChar c = (' ' <= c && c <= '\xD7FF') || ('\xE000' <= c)++-- this is the lowest number used for a list numId+baseListId :: Int+baseListId = 1000++getNumId :: (PandocMonad m) => WS m Int+getNumId = gets (((baseListId - 1) +) . length . stLists)++makeTOC :: (PandocMonad m) => WriterOptions -> WS m [Element]+makeTOC opts = do+  let depth = "1-" <> tshow (writerTOCDepth opts)+  let tocCmd = "TOC \\o \"" <> depth <> "\" \\h \\z \\u"+  tocTitle <- gets stTocTitle+  title <- withParaPropM (pStyleM "TOC Heading") (blocksToOpenXML opts [Para tocTitle])+  return+    [mknode "w:sdt" [] [+      mknode "w:sdtPr" [] (+        mknode "w:docPartObj" []+          [mknode "w:docPartGallery" [("w:val","Table of Contents")] (),+          mknode "w:docPartUnique" [] ()]+         -- w:docPartObj+      ), -- w:sdtPr+      mknode "w:sdtContent" [] (title ++ [ Elem $+        mknode "w:p" [] (+          mknode "w:r" [] [+            mknode "w:fldChar" [("w:fldCharType","begin"),("w:dirty","true")] (),+            mknode "w:instrText" [("xml:space","preserve")] tocCmd,+            mknode "w:fldChar" [("w:fldCharType","separate")] (),+            mknode "w:fldChar" [("w:fldCharType","end")] ()+          ] -- w:r+        ) -- w:p+      ])+    ]] -- w:sdt++-- | Convert Pandoc document to rendered document contents plus two lists of+-- OpenXML elements (footnotes and comments).+writeOpenXML :: PandocMonad m+             => WriterOptions -> Pandoc+             -> WS m (Text, [Element], [Element])+writeOpenXML opts (Pandoc meta blocks) = do+  setupTranslations meta+  let includeTOC = writerTableOfContents opts || lookupMetaBool "toc" meta+  abstractTitle <- case lookupMeta "abstract-title" meta of+      Just (MetaBlocks bs)   -> pure $ stringify bs+      Just (MetaInlines ils) -> pure $ stringify ils+      Just (MetaString s)    -> pure s+      _                      -> translateTerm Abstract+  abstract <-+    case lookupMetaBlocks "abstract" meta of+      [] -> return mempty+      xs -> vcat . map (literal . showContent) <$>+              withParaPropM (pStyleM "Abstract") (blocksToOpenXML opts xs)++  let toInlineMeta field = hcat . map (literal . showContent) <$>+         inlinesToOpenXML opts (lookupMetaInlines field meta)++  title <- toInlineMeta "title"+  subtitle <- toInlineMeta "subtitle"+  date <- toInlineMeta "date"++  author <- mapM+             (fmap (hcat . map (literal . showContent)) . inlinesToOpenXML opts)+             (docAuthors meta)++  doc' <- setFirstPara >> blocksToOpenXML opts blocks+  let body = vcat $ map (literal . showContent) doc'+  notes' <- gets (reverse . stFootnotes)+  comments <- gets (reverse . stComments)+  let toComment (kvs, ils) = do+        annotation <- inlinesToOpenXML opts ils+        return $+          mknode "w:comment" [("w:" <> k, v) | (k,v) <- kvs]+            [ mknode "w:p" [] $+              map Elem+              [ mknode "w:pPr" []+                [ mknode "w:pStyle" [("w:val", "CommentText")] () ]+              , mknode "w:r" []+                [ mknode "w:rPr" []+                  [ mknode "w:rStyle" [("w:val", "CommentReference")] ()+                  ]+                  , mknode "w:annotationRef" [] ()+                ]+              ] ++ annotation+            ]+  comments' <- mapM toComment comments+  toc <- if includeTOC+            then makeTOC opts+            else return []+  metadata <- metaToContext opts+                 (fmap (vcat . map (literal . showContent)) . blocksToOpenXML opts)+                 (fmap (hcat . map (literal . showContent)) . inlinesToOpenXML opts)+                 meta+  let context = resetField "body" body+              . resetField "toc"+                   (vcat (map (literal . showElement) toc))+              . resetField "title" title+              . resetField "subtitle" subtitle+              . resetField "author" author+              . resetField "date" date+              . resetField "abstract-title" abstractTitle+              . resetField "abstract" abstract+              $ metadata+  tpl <- maybe (lift $ compileDefaultTemplate "openxml") pure $ writerTemplate opts+  let rendered = render Nothing $ renderTemplate tpl context+  return (rendered, notes', comments')++-- | Convert a list of Pandoc blocks to OpenXML.+blocksToOpenXML :: (PandocMonad m) => WriterOptions -> [Block] -> WS m [Content]+blocksToOpenXML opts = fmap concat . mapM (blockToOpenXML opts) . separateTables . filter (not . isForeignRawBlock)++isForeignRawBlock :: Block -> Bool+isForeignRawBlock (RawBlock format _) = format /= "openxml"+isForeignRawBlock _                   = False++-- Word combines adjacent tables unless you put an empty paragraph between+-- them.  See #4315.+separateTables :: [Block] -> [Block]+separateTables [] = []+separateTables (x@Table{}:xs@(Table{}:_)) =+  x : RawBlock (Format "openxml") "<w:p />" : separateTables xs+separateTables (x:xs) = x : separateTables xs++rStyleM :: (PandocMonad m) => CharStyleName -> WS m XML.Element+rStyleM styleName = do+  cStyleMap <- gets (smCharStyle . stStyleMaps)+  let sty' = getStyleIdFromName styleName cStyleMap+  return $ mknode "w:rStyle" [("w:val", fromStyleId sty')] ()++getUniqueId :: (PandocMonad m) => WS m Text+getUniqueId = do+  n <- gets stCurId+  modify $ \st -> st{stCurId = n + 1}+  return $ tshow n++-- | Key for specifying user-defined docx styles.+dynamicStyleKey :: Text+dynamicStyleKey = "custom-style"++-- | Convert a Pandoc block element to OpenXML.+blockToOpenXML :: (PandocMonad m) => WriterOptions -> Block -> WS m [Content]+blockToOpenXML opts blk = withDirection $ blockToOpenXML' opts blk++blockToOpenXML' :: (PandocMonad m) => WriterOptions -> Block -> WS m [Content]+blockToOpenXML' opts (Div (ident,_classes,kvs) bs) = do+  stylemod <- case lookup dynamicStyleKey kvs of+                   Just (fromString . T.unpack -> sty) -> do+                      modify $ \s ->+                        s{stDynamicParaProps = Set.insert sty+                             (stDynamicParaProps s)}+                      return $ withParaPropM (pStyleM sty)+                   _ -> return id+  dirmod <- case lookup "dir" kvs of+                 Just "rtl" -> return $ local (\env -> env { envRTL = True })+                 Just "ltr" -> return $ local (\env -> env { envRTL = False })+                 _ -> return id+  let (hs, bs') = if ident == "refs"+                     then span isHeaderBlock bs+                     else ([], bs)+  let bibmod = if ident == "refs"+                  then withParaPropM (pStyleM "Bibliography")+                  else id+  let langmod = case lookup "lang" kvs of+                  Nothing -> id+                  Just lang -> local (\env -> env{envLang = Just lang})+  header <- dirmod $ stylemod $ blocksToOpenXML opts hs+  contents <- dirmod $ bibmod $ stylemod $ langmod $ blocksToOpenXML opts bs'+  wrapBookmark ident $ header <> contents+blockToOpenXML' opts (Header lev (ident,_,kvs) lst) = do+  setFirstPara+  paraProps <- withParaPropM (pStyleM (fromString $ "Heading "++show lev)) $+                    getParaProps False+  number <-+        if writerNumberSections opts+           then+             case lookup "number" kvs of+                Just n -> do+                   num <- withTextPropM (rStyleM "SectionNumber")+                            (inlineToOpenXML opts (Str n))+                   return $ num ++ [Elem $ mknode "w:r" [] [mknode "w:tab" [] ()]]+                Nothing -> return []+           else return []+  contents <- (number ++) <$> inlinesToOpenXML opts lst+  if T.null ident+     then return [Elem $ mknode "w:p" [] (map Elem paraProps ++ contents)]+     else do+       let bookmarkName = ident+       modify $ \s -> s{ stSectionIds = Set.insert bookmarkName+                                      $ stSectionIds s }+       bookmarkedContents <- wrapBookmark bookmarkName contents+       return [Elem $ mknode "w:p" [] (map Elem paraProps ++ bookmarkedContents)]+blockToOpenXML' opts (Plain lst) = do+  isInTable <- gets stInTable+  isInList <- gets stInList+  let block = blockToOpenXML opts (Para lst)+  prop <- pStyleM "Compact"+  if isInTable || isInList+     then withParaProp prop block+     else block+blockToOpenXML' opts (Para lst)+  | null lst && not (isEnabled Ext_empty_paragraphs opts) = return []+  | otherwise = do+      isFirstPara <- gets stFirstPara+      let displayMathPara = case lst of+                                 [x] -> isDisplayMath x+                                 _   -> False+      paraProps <- getParaProps displayMathPara+      bodyTextStyle <- pStyleM $ if isFirstPara+                       then "First Paragraph"+                       else "Body Text"+      let paraProps' = case paraProps of+            []               -> [mknode "w:pPr" [] [bodyTextStyle]]+            ps               -> ps+      modify $ \s -> s { stFirstPara = False }+      contents <- inlinesToOpenXML opts lst+      return [Elem $ mknode "w:p" [] (map Elem paraProps' ++ contents)]+blockToOpenXML' opts (LineBlock lns) = blockToOpenXML opts $ linesToPara lns+blockToOpenXML' _ b@(RawBlock format str)+  | format == Format "openxml" = return [+        Text (CData CDataRaw str Nothing)+      ]+  | otherwise                  = do+      report $ BlockNotRendered b+      return []+blockToOpenXML' opts (BlockQuote blocks) = do+  inNote <- asks envInNote+  p <- withParaPropM (pStyleM+                       (if inNote+                           then "Footnote Block Text"+                           else "Block Text"))+       $ blocksToOpenXML opts blocks+  setFirstPara+  return p+blockToOpenXML' opts (CodeBlock attrs@(ident, _, _) str) = do+  p <- withParaPropM (pStyleM "Source Code") (blockToOpenXML opts $ Para [Code attrs str])+  setFirstPara+  wrapBookmark ident p+blockToOpenXML' _ HorizontalRule = do+  setFirstPara+  return [ Elem $+    mknode "w:p" [] $ mknode "w:r" [] $ mknode "w:pict" []+    $ mknode "v:rect" [("style","width:0;height:1.5pt"),+                       ("o:hralign","center"),+                       ("o:hrstd","t"),("o:hr","t")] () ]+blockToOpenXML' opts (Table attr caption colspecs thead tbodies tfoot) = do+  -- Remove extra paragraph indentation due to list items (#5947).+  -- This means that tables in lists will not be indented, but it+  -- avoids unwanted indentation in each cell.+  content <- tableToOpenXML opts+              (local (\env -> env{ envListLevel = -1 }) . blocksToOpenXML opts)+                 (Grid.toTable attr caption colspecs thead tbodies tfoot)+  let (tableId, _, _) = attr+  wrapBookmark tableId content+blockToOpenXML' opts el+  | BulletList lst <- el+  = case mapM toTaskListItem lst of+      Just items -> addOpenXMLList (map (first (Just . CheckboxMarker)) items)+      Nothing -> addOpenXMLList $ zip (Just BulletMarker : repeat Nothing) lst+  | OrderedList (start, numstyle, numdelim) lst <- el+  = addOpenXMLList $+    zip (Just (NumberMarker numstyle numdelim start) : repeat Nothing) lst+  where+    addOpenXMLList items = do+      exampleid <- case items of+                        (Just (NumberMarker Example _ _),_) : _ -> gets stExampleId+                        _ -> return Nothing+      l <- asList $ mconcat <$>+              mapM (\(mbmarker, bs) -> do+                      numid <- case mbmarker of+                        Nothing -> getNumId+                        Just marker -> do+                          addList marker+                          getNumId+                      listItemToOpenXML opts (fromMaybe numid exampleid) bs)+              items+      setFirstPara+      return l+blockToOpenXML' opts (DefinitionList items) = do+  l <- concat `fmap` mapM (definitionListItemToOpenXML opts) items+  setFirstPara+  return l+blockToOpenXML' opts (Figure (ident, _, _) (Caption _ longcapt) body) = do+  setFirstPara+  fignum <- gets stNextFigureNum+  unless (null longcapt) $ modify $ \st -> st{ stNextFigureNum = fignum + 1 }+  let refid = if T.null ident+              then "ref_fig" <> tshow fignum+              else "ref_" <> ident+  figname <- translateTerm Term.Figure+  prop <- pStyleM $+    if null longcapt+    then "Figure"+    else "Captioned Figure"+  paraProps <- local+    (\env -> env { envParaProperties = EnvProps (Just prop) [] <>+                                       envParaProperties env })+    (getParaProps False)++  -- Figure contents+  let simpleImage x = do+        imgXML <- inlineToOpenXML opts x+        pure $ Elem (mknode "w:p" [] (map Elem paraProps ++ imgXML))+  contentsNode <- case body of+    [Plain [img@Image {}]] -> simpleImage img+    [Para  [img@Image {}]] -> simpleImage img+    _                      -> toFigureTable opts body+  -- Caption+  let imageCaption = withParaPropM (pStyleM "Image Caption")+                   . blocksToOpenXML opts+  let fstCaptionPara inlns = Para $+        if not $ isEnabled Ext_native_numbering opts+        then inlns+        else let rawfld = RawInline (Format "openxml") $ mconcat+                          [ "<w:fldSimple w:instr=\"SEQ Figure"+                          , " \\* ARABIC \"><w:r><w:t>"+                          , tshow fignum+                          , "</w:t></w:r></w:fldSimple>"+                          ]+             in Span (refid,[],[]) [Str (figname <> "\160") , rawfld]+                : Str ": " : inlns+  captionNode <- case longcapt of+    []              -> return []+    (Para xs  : bs) -> imageCaption (fstCaptionPara xs : bs)+    (Plain xs : bs) -> imageCaption (fstCaptionPara xs : bs)+    _               -> imageCaption longcapt+  wrapBookmark ident $ contentsNode : captionNode++toFigureTable :: PandocMonad m+              => WriterOptions -> [Block] -> WS m Content+toFigureTable opts blks = do+  modify $ \s -> s { stInTable = True }+  let ncols = length blks+  let textwidth = 7920  -- 5.5 in in twips       (1 twip == 1/20 pt)+  let cellfrac = 1 / fromIntegral ncols+  let colwidth = tshow @Integer $ floor (textwidth * cellfrac) -- twips+  let gridCols = replicate ncols $ mknode "w:gridCol" [("w:w", colwidth)] ()+  let scaleImage = \case+        Image attr@(ident, classes, attribs) alt tgt ->+          let dimWidth  = case dimension Width attr of+                            Nothing -> Percent (cellfrac * 100)+                            Just d  -> scaleDimension cellfrac d+              dimHeight = scaleDimension cellfrac <$> dimension Height attr+              attribs' = (tshow Width, tshow dimWidth) :+                         (case dimHeight of+                            Nothing -> id+                            Just h  -> ((tshow Height, tshow h) :))+                         [ (k, v) | (k, v) <- attribs+                                  , k `notElem` ["width", "height"]+                                  ]+          in Image (ident, classes, attribs') alt tgt+        x -> x+  let blockToCell = Table.OOXMLCell nullAttr AlignCenter 1 1 . (:[])+                  . walk scaleImage+  tblBody <- Table.rowToOpenXML (blocksToOpenXML opts) .+             Table.OOXMLRow Table.BodyRow nullAttr $+             map blockToCell blks+  let tbl = mknode "w:tbl" []+        ( mknode "w:tblPr" []+          [ mknode "w:tblStyle" [("w:val","FigureTable")] (),+            mknode "w:tblW" [ ("w:type", "auto"), ("w:w", "0") ] (),+            mknode "w:jc" [("w:val","center")] (),+            mknode "w:tblLook" [ ("w:firstRow", "0")+                               , ("w:lastRow", "0")+                               , ("w:firstColumn", "0")+                               , ("w:lastColumn", "0")+                               ] ()+          ]+          : mknode "w:tblGrid" [] gridCols+          : maybeToList tblBody+        )+  modify $ \s -> s { stInTable = False }+  return $ Elem tbl+++definitionListItemToOpenXML  :: (PandocMonad m)+                             => WriterOptions -> ([Inline],[[Block]])+                             -> WS m [Content]+definitionListItemToOpenXML opts (term,defs) = do+  term' <- withParaPropM (pStyleM "Definition Term")+           $ blockToOpenXML opts (Para term)+  defs' <- withParaPropM (pStyleM "Definition")+           $ concat `fmap` mapM (blocksToOpenXML opts) defs+  return $ term' ++ defs'++addList :: (PandocMonad m) => ListMarker -> WS m ()+addList marker = do+  lists <- gets stLists+  lastExampleId <- gets stExampleId+  modify $ \st -> st{ stLists = lists ++ case marker of+                                         -- Use only first occurrence of Example for list declaration to avoid overhead+                                         NumberMarker Example _ _ | isJust lastExampleId -> []+                                         _ -> [marker]+                    , stExampleId = case marker of+                                         -- Reuse the same identifier for all other occurrences of Example+                                         NumberMarker Example _ _ -> lastExampleId <|> Just (baseListId + length lists)+                                         _ -> lastExampleId+                  }++listItemToOpenXML :: (PandocMonad m)+                  => WriterOptions+                  -> Int -> [Block]+                  -> WS m [Content]+listItemToOpenXML opts numid bs = do+  oldInList <- gets stInList+  modify $ \st -> st{ stInList = True }+  let isListBlock = \case+        BulletList{}  -> True+        OrderedList{} -> True+        _             -> False+  -- Prepend an empty string if the first entry is another+  -- list. Otherwise the outer bullet will disappear.+  let bs' = case bs of+                 [] -> []+                 x:xs -> if isListBlock x+                               then Plain [Str ""]:x:xs+                               else x:xs+  modify $ \st -> st{ stNumIdUsed = False }+  contents <- withNumId numid $ blocksToOpenXML opts bs'+  modify $ \st -> st{ stInList = oldInList }+  return contents++-- | Convert a list of inline elements to OpenXML.+inlinesToOpenXML :: PandocMonad m => WriterOptions -> [Inline] -> WS m [Content]+inlinesToOpenXML opts lst = concat `fmap` mapM (inlineToOpenXML opts) (convertSpace lst)++withNumId :: (PandocMonad m) => Int -> WS m a -> WS m a+withNumId numid = local $ \env -> env{ envListNumId = numid }++asList :: (PandocMonad m) => WS m a -> WS m a+asList = local $ \env -> env{ envListLevel = envListLevel env + 1 }++getTextProps :: (PandocMonad m) => WS m [Element]+getTextProps = do+  props <- asks envTextProperties+  mblang <- asks envLang+  let langnode = case mblang of+                   Nothing -> mempty+                   Just l  -> EnvProps Nothing+                               [mknode "w:lang" [("w:val", l)] ()]+  let squashed = squashProps (props <> langnode)+  return [mknode "w:rPr" [] squashed | (not . null) squashed]++withTextProp :: PandocMonad m => Element -> WS m a -> WS m a+withTextProp d p =+  local (\env -> env {envTextProperties = ep <> envTextProperties env}) p+  where ep = if isStyle d then EnvProps (Just d) [] else EnvProps Nothing [d]++withTextPropM :: PandocMonad m => WS m Element -> WS m a -> WS m a+withTextPropM md p = do+  d <- md+  withTextProp d p++getParaProps :: PandocMonad m => Bool -> WS m [Element]+getParaProps displayMathPara = do+  props <- asks envParaProperties+  listLevel <- asks envListLevel+  numid <- asks envListNumId+  numIdUsed <- gets stNumIdUsed+  -- clear numId after first use to support multiple paragraphs in the same bullet+  -- baseListId is the code for no list marker+  let numid' = if numIdUsed then baseListId else numid+  modify $ \st -> st{ stNumIdUsed = True }+  let listPr = [mknode "w:numPr" []+                [ mknode "w:ilvl" [("w:val",tshow listLevel)] ()+                , mknode "w:numId" [("w:val",tshow numid')] () ] | listLevel >= 0 && not displayMathPara]+  return $ case squashProps (EnvProps Nothing listPr <> props) of+                [] -> []+                ps -> [mknode "w:pPr" [] ps]++formattedString :: PandocMonad m => Text -> WS m [Element]+formattedString str =+  -- properly handle soft hyphens+  case splitTextBy (=='\173') str of+      [w] -> formattedString' w+      ws  -> do+         sh <- formattedRun [mknode "w:softHyphen" [] ()]+         intercalate [sh] <$> mapM formattedString' ws++formattedString' :: PandocMonad m => Text -> WS m [Element]+formattedString' str = do+  inDel <- asks envInDel+  let mkrun s =+        (if T.any isCJK s+            then withTextProp (mknode "w:rFonts" [("w:hint","eastAsia")] ())+            else id) $ formattedRun+                       [ mktnode (if inDel then "w:delText" else "w:t")+                          [("xml:space","preserve")] $ s ]+  mapM mkrun $ breakIntoChunks $ stripInvalidChars str++-- For motivation see #9817.+breakIntoChunks :: Text -> [Text]+breakIntoChunks t+  | T.null t = []+  | T.any isCJK t+    = let cs = T.groupBy (\c d -> (isSpace c && isSpace d) ||+                                  not (isSpace c || isSpace d)) t+          css = groupBy (\x y -> not (T.any isCJK x || T.any isCJK y)+                                  || (T.all isSpace x && not (T.any isCJK y))+                                  || (T.all isSpace y && not (T.any isCJK x)))+                        cs+       in map mconcat css+  | otherwise = [t]++formattedRun :: PandocMonad m => [Element] -> WS m Element+formattedRun els = do+  props <- getTextProps+  return $ mknode "w:r" [] $ props ++ els++-- | Convert an inline element to OpenXML.+inlineToOpenXML :: PandocMonad m => WriterOptions -> Inline -> WS m [Content]+inlineToOpenXML opts il = withDirection $ inlineToOpenXML' opts il++inlineToOpenXML' :: PandocMonad m => WriterOptions -> Inline -> WS m [Content]+inlineToOpenXML' _ (Str str) =+  map Elem <$> formattedString str+inlineToOpenXML' opts Space = inlineToOpenXML opts (Str " ")+inlineToOpenXML' opts SoftBreak = inlineToOpenXML opts (Str " ")+inlineToOpenXML' opts (Span ("",["mark"],[]) ils) =+  withTextProp (mknode "w:highlight" [("w:val","yellow")] ()) $+    inlinesToOpenXML opts ils+inlineToOpenXML' opts (Span ("",["csl-block"],[]) ils) =+  inlinesToOpenXML opts ils+inlineToOpenXML' opts (Span ("",["csl-left-margin"],[]) ils) =+  inlinesToOpenXML opts ils+inlineToOpenXML' opts (Span ("",["csl-right-inline"],[]) ils) =+   ([Elem $+     mknode "w:r" []+     (mknode "w:t"+       [("xml:space","preserve")]+       ("\t" :: Text))] ++)+    <$> inlinesToOpenXML opts ils+inlineToOpenXML' opts (Span ("",["csl-indent"],[]) ils) =+  inlinesToOpenXML opts ils+inlineToOpenXML' _ (Span (ident,["comment-start"],kvs) ils) = do+  -- prefer the "id" in kvs, since that is the one produced by the docx+  -- reader.+  let ident' = fromMaybe ident (lookup "id" kvs)+      kvs' = filter (("id" /=) . fst) kvs+  modify $ \st -> st{ stComments = (("id",ident'):kvs', ils) : stComments st }+  return [ Elem $ mknode "w:commentRangeStart" [("w:id", ident')] () ]+inlineToOpenXML' _ (Span (ident,["comment-end"],kvs) _) =+  -- prefer the "id" in kvs, since that is the one produced by the docx+  -- reader.+  let ident' = fromMaybe ident (lookup "id" kvs)+  in return . map Elem $+     [ mknode "w:commentRangeEnd" [("w:id", ident')] ()+     , mknode "w:r" []+       [ mknode "w:rPr" []+         [ mknode "w:rStyle" [("w:val", "CommentReference")] () ]+       , mknode "w:commentReference" [("w:id", ident')] () ]+     ]+inlineToOpenXML' opts (Span (ident,classes,kvs) ils) = do+  stylemod <- case lookup dynamicStyleKey kvs of+                   Just (fromString . T.unpack -> sty) -> do+                      modify $ \s ->+                        s{stDynamicTextProps = Set.insert sty+                              (stDynamicTextProps s)}+                      return $ withTextPropM (rStyleM sty)+                   _ -> return id+  let dirmod = case lookup "dir" kvs of+                 Just "rtl" -> local (\env -> env { envRTL = True })+                 Just "ltr" -> local (\env -> env { envRTL = False })+                 _          -> id+      off x = withTextProp (mknode x [("w:val","0")] ())+      pmod =  (if "csl-no-emph" `elem` classes then off "w:i" else id) .+              (if "csl-no-strong" `elem` classes then off "w:b" else id) .+              (if "csl-no-smallcaps" `elem` classes+                  then off "w:smallCaps"+                  else id)+      getChangeAuthorDate = do+        defaultAuthor <- asks envChangesAuthor+        let author = fromMaybe defaultAuthor (lookup "author" kvs)+        let mdate = lookup "date" kvs+        return $ ("w:author", author) :+                   maybe [] (\date -> [("w:date", date)]) mdate+  insmod <- if "insertion" `elem` classes+               then do+                 changeAuthorDate <- getChangeAuthorDate+                 insId <- gets stInsId+                 modify $ \s -> s{stInsId = insId + 1}+                 return $ \f -> do+                   x <- f+                   return [Elem $+                           mknode "w:ins"+                             (("w:id", tshow insId) : changeAuthorDate) x]+               else return id+  delmod <- if "deletion" `elem` classes+               then do+                 changeAuthorDate <- getChangeAuthorDate+                 delId <- gets stDelId+                 modify $ \s -> s{stDelId = delId + 1}+                 return $ \f -> local (\env->env{envInDel=True}) $ do+                   x <- f+                   return [Elem $ mknode "w:del"+                             (("w:id", tshow delId) : changeAuthorDate) x]+               else return id+  let langmod = case lookup "lang" kvs of+                  Nothing -> id+                  Just lang -> local (\env -> env{envLang = Just lang})+  contents <- insmod $ delmod $ dirmod $ stylemod $ pmod $+              langmod $ inlinesToOpenXML opts ils+  wrapBookmark ident contents+inlineToOpenXML' opts (Strong lst) =+  withTextProp (mknode "w:bCs" [] ()) $ -- needed for LTR, #6911+  withTextProp (mknode "w:b" [] ()) $+  inlinesToOpenXML opts lst+inlineToOpenXML' opts (Emph lst) =+  withTextProp (mknode "w:iCs" [] ()) $  -- needed for LTR, #6911+  withTextProp (mknode "w:i" [] ()) $+  inlinesToOpenXML opts lst+inlineToOpenXML' opts (Underline lst) =+  withTextProp (mknode "w:u" [("w:val","single")] ()) $+    inlinesToOpenXML opts lst+inlineToOpenXML' opts (Subscript lst) =+  withTextProp (mknode "w:vertAlign" [("w:val","subscript")] ())+  $ inlinesToOpenXML opts lst+inlineToOpenXML' opts (Superscript lst) =+  withTextProp (mknode "w:vertAlign" [("w:val","superscript")] ())+  $ inlinesToOpenXML opts lst+inlineToOpenXML' opts (SmallCaps lst) =+  withTextProp (mknode "w:smallCaps" [] ())+  $ inlinesToOpenXML opts lst+inlineToOpenXML' opts (Strikeout lst) =+  withTextProp (mknode "w:strike" [] ())+  $ inlinesToOpenXML opts lst+inlineToOpenXML' _ LineBreak = return [Elem br]+inlineToOpenXML' _ il@(RawInline f str)+  | f == Format "openxml" = return+                            [Text (CData CDataRaw str Nothing)]+  | otherwise             = do+      report $ InlineNotRendered il+      return []+inlineToOpenXML' opts (Quoted quoteType lst) =+  inlinesToOpenXML opts $ [Str open] ++ lst ++ [Str close]+    where (open, close) = case quoteType of+                            SingleQuote -> ("\x2018", "\x2019")+                            DoubleQuote -> ("\x201C", "\x201D")+inlineToOpenXML' opts (Math mathType str) = do+  when (mathType == DisplayMath) setFirstPara+  res <- (lift . lift) (convertMath writeOMML mathType str)+  case res of+       Right r -> return [Elem $ fromXLElement r]+       Left il -> inlineToOpenXML' opts il+inlineToOpenXML' opts (Cite _ lst) = inlinesToOpenXML opts lst+inlineToOpenXML' opts (Code attrs str) = do+  let alltoktypes = [KeywordTok ..]+  tokTypesMap <- mapM (\tt -> (,) tt <$> rStyleM (fromString $ show tt)) alltoktypes+  let unhighlighted = (map Elem . intercalate [br]) `fmap`+                       mapM formattedString (T.lines str)+      formatOpenXML _fmtOpts = intercalate [br] . map (map toHlTok)+      toHlTok (toktype,tok) =+        mknode "w:r" []+          [ mknode "w:rPr" [] $+            maybeToList (lookup toktype tokTypesMap)+            , mknode "w:t" [("xml:space","preserve")] tok ]+  withTextPropM (rStyleM "Verbatim Char")+    $ if isNothing (writerHighlightStyle opts)+          then unhighlighted+          else case highlight (writerSyntaxMap opts)+                      formatOpenXML attrs str of+                    Right h  -> return (map Elem h)+                    Left msg -> do+                      unless (T.null msg) $ report $ CouldNotHighlight msg+                      unhighlighted+inlineToOpenXML' opts (Note bs) = do+  notes <- gets stFootnotes+  notenum <- getUniqueId+  footnoteStyle <- rStyleM "Footnote Reference"+  let notemarker = mknode "w:r" []+                   [ mknode "w:rPr" [] footnoteStyle+                   , mknode "w:footnoteRef" [] () ]+  let notemarkerXml = RawInline (Format "openxml") $ ppElement notemarker+  let insertNoteRef (Plain ils : xs) = Plain (notemarkerXml : Space : ils) : xs+      insertNoteRef (Para ils  : xs) = Para  (notemarkerXml : Space : ils) : xs+      insertNoteRef xs               = Para [notemarkerXml] : xs++  contents <- local (\env -> env{ envListLevel = -1+                                , envParaProperties = mempty+                                , envTextProperties = mempty+                                , envInNote = True })+              (withParaPropM (pStyleM "Footnote Text") $+               blocksToOpenXML opts $ insertNoteRef bs)+  let newnote = mknode "w:footnote" [("w:id", notenum)] contents+  modify $ \s -> s{ stFootnotes = newnote : notes }+  return [ Elem $ mknode "w:r" []+           [ mknode "w:rPr" [] footnoteStyle+           , mknode "w:footnoteReference" [("w:id", notenum)] () ] ]+-- internal link:+inlineToOpenXML' opts (Link _ txt (T.uncons -> Just ('#', xs),_)) = do+  contents <- withTextPropM (rStyleM "Hyperlink") $ inlinesToOpenXML opts txt+  return+    [ Elem $ mknode "w:hyperlink" [("w:anchor", toBookmarkName xs)] contents ]+-- external link:+inlineToOpenXML' opts (Link _ txt (src,_)) = do+  contents <- withTextPropM (rStyleM "Hyperlink") $ inlinesToOpenXML opts txt+  extlinks <- gets stExternalLinks+  id' <- case M.lookup src extlinks of+            Just i   -> return i+            Nothing  -> do+              i <- ("rId" <>) <$> getUniqueId+              modify $ \st -> st{ stExternalLinks =+                        M.insert src i extlinks }+              return i+  return [ Elem $ mknode "w:hyperlink" [("r:id",id')] contents ]+inlineToOpenXML' opts (Image attr@(imgident, _, _) alt (src, title)) = do+  pageWidth <- asks envPrintWidth+  imgs <- gets stImages+  let+    stImage = M.lookup (T.unpack src) imgs+    generateImgElt (ident, _fp, mt, img) = do+      docprid <- getUniqueId+      nvpicprid <- getUniqueId+      (blipAttrs, blipContents) <-+        case T.takeWhile (/=';') <$> mt of+          Just "image/svg+xml" -> do+            -- get fallback png+            mediabag <- getMediaBag+            mbFallback <-+              case lookupMedia (T.unpack (src <> ".png")) mediabag of+                Just item -> do+                  id' <- T.unpack . ("rId" <>) <$> getUniqueId+                  let fp' = "media/" <> id' <> ".png"+                  let imgdata = (id',+                                 fp',+                                 Just (mediaMimeType item),+                                 BL.toStrict $ mediaContents item)+                  modify $ \st -> st { stImages =+                            M.insert fp' imgdata $ stImages st }+                  return $ Just id'+                Nothing -> return Nothing+            let extLst = mknode "a:extLst" []+                            [ mknode "a:ext"+                              [("uri","{28A0092B-C50C-407E-A947-70E740481C1C}")]+                              [ mknode "a14:useLocalDpi"+                                [("xmlns:a14","http://schemas.microsoft.com/office/drawing/2010/main"),+                                 ("val","0")] () ]+                            , mknode "a:ext"+                              [("uri","{96DAC541-7B7A-43D3-8B79-37D633B846F1}")]+                              [ mknode "asvg:svgBlip"+                                [("xmlns:asvg", "http://schemas.microsoft.com/office/drawing/2016/SVG/main"),+                                 ("r:embed",T.pack ident)] () ]+                            ]+            return (maybe [] (\id'' -> [("r:embed", T.pack id'')]) mbFallback,+                    [extLst])+          _ -> return ([("r:embed", T.pack ident)], [])+      let+        (xpt,ypt) = desiredSizeInPoints opts attr+               (either (const def) id (imageSize opts img))+        -- 12700 emu = 1 pt+        pageWidthPt = case dimension Width attr of+                        Just (Percent a) -> pageWidth * floor (a * 127)+                        _                -> pageWidth * 12700+        (xemu,yemu) = fitToPage (xpt * 12700, ypt * 12700) pageWidthPt+        cNvPicPr = mknode "pic:cNvPicPr" [] $+                         mknode "a:picLocks" [("noChangeArrowheads","1")+                                             ,("noChangeAspect","1")] ()+        nvPicPr  = mknode "pic:nvPicPr" []+                        [ mknode "pic:cNvPr"+                            [("descr",src)+                            ,("id", nvpicprid)+                            ,("name","Picture")] ()+                        , cNvPicPr ]+        blipFill = mknode "pic:blipFill" []+          [ mknode "a:blip" blipAttrs blipContents+          , mknode "a:stretch" [] $+              mknode "a:fillRect" [] ()+          ]+        xfrm =    mknode "a:xfrm" []+                        [ mknode "a:off" [("x","0"),("y","0")] ()+                        , mknode "a:ext" [("cx",tshow xemu)+                                         ,("cy",tshow yemu)] () ]+        prstGeom = mknode "a:prstGeom" [("prst","rect")] $+                         mknode "a:avLst" [] ()+        ln =      mknode "a:ln" [("w","9525")]+                        [ mknode "a:noFill" [] ()+                        , mknode "a:headEnd" [] ()+                        , mknode "a:tailEnd" [] () ]+        spPr =    mknode "pic:spPr" [("bwMode","auto")]+                        [xfrm, prstGeom, mknode "a:noFill" [] (), ln]+        graphic = mknode "a:graphic" [] $+          mknode "a:graphicData"+            [("uri","http://schemas.openxmlformats.org/drawingml/2006/picture")]+            [ mknode "pic:pic" []+              [ nvPicPr+              , blipFill+              , spPr+              ]+            ]+        imgElt = mknode "w:r" [] $+          mknode "w:drawing" [] $+            mknode "wp:inline" []+              [ mknode "wp:extent" [("cx",tshow xemu),("cy",tshow yemu)] ()+              , mknode "wp:effectExtent"+                [("b","0"),("l","0"),("r","0"),("t","0")] ()+              , mknode "wp:docPr"+                [ ("descr", stringify alt)+                , ("title", title)+                , ("id", docprid)+                , ("name","Picture")+                ] ()+              , graphic+              ]+      return [Elem imgElt]++  wrapBookmark imgident =<< case stImage of+    Just imgData -> generateImgElt imgData+    Nothing -> ( do --try+      (img, mt) <- P.fetchItem src+      ident <- ("rId" <>) <$> getUniqueId++      let+        imgext = case mt >>= extensionFromMimeType of+          Just x    -> "." <> x+          Nothing   -> case imageType img of+            Just Png  -> ".png"+            Just Jpeg -> ".jpeg"+            Just Gif  -> ".gif"+            Just Pdf  -> ".pdf"+            Just Eps  -> ".eps"+            Just Svg  -> ".svg"+            Just Emf  -> ".emf"+            Just Tiff -> ".tiff"+            Nothing   -> ""+        imgpath = "media/" <> ident <> imgext+        mbMimeType = mt <|> getMimeType (T.unpack imgpath)++        imgData = (T.unpack ident, T.unpack imgpath, mbMimeType, img)++      if T.null imgext+         then -- without an extension there is no rule for content type+           inlinesToOpenXML opts alt -- return alt to avoid corrupted docx+         else do+           -- insert mime type to use in constructing [Content_Types].xml+           modify $ \st -> st { stImages = M.insert (T.unpack src) imgData $ stImages st }+           generateImgElt imgData+      )+      `catchError` ( \e -> do+        report $ CouldNotFetchResource src $ T.pack (show e)+        -- emit alt text+        inlinesToOpenXML opts alt+      )++br :: Element+br = mknode "w:r" [] [mknode "w:br" [] ()]+++withDirection :: PandocMonad m => WS m a -> WS m a+withDirection x = do+  isRTL <- asks envRTL+  paraProps <- asks envParaProperties+  textProps <- asks envTextProperties+  -- We want to clean all bidirection (bidi) and right-to-left (rtl)+  -- properties from the props first. This is because we don't want+  -- them to stack up.+  let paraProps' = filter (\e -> (qName . elName) e /= "bidi") (otherElements paraProps)+      textProps' = filter (\e -> (qName . elName) e /= "rtl") (otherElements textProps)+      paraStyle = styleElement paraProps+      textStyle = styleElement textProps+  if isRTL+    -- if we are going right-to-left, we (re?)add the properties.+    then flip local x $+         \env -> env { envParaProperties = EnvProps paraStyle $ mknode "w:bidi" [] () : paraProps'+                     , envTextProperties = EnvProps textStyle $ mknode "w:rtl" [] () : textProps'+                     }+    else flip local x $ \env -> env { envParaProperties = EnvProps paraStyle paraProps'+                                    , envTextProperties = EnvProps textStyle textProps'+                                    }++wrapBookmark :: (PandocMonad m) => Text -> [Content] -> WS m [Content]+wrapBookmark "" contents = return contents+wrapBookmark ident contents = do+  id' <- getUniqueId+  let bookmarkStart = mknode "w:bookmarkStart"+                       [("w:id", id')+                       ,("w:name", toBookmarkName ident)] ()+      bookmarkEnd = mknode "w:bookmarkEnd" [("w:id", id')] ()+  return $ Elem bookmarkStart : contents ++ [Elem bookmarkEnd]++-- Word imposes a 40 character limit on bookmark names and requires+-- that they begin with a letter.  So we just use a hash of the+-- identifier when otherwise we'd have an illegal bookmark name.+toBookmarkName :: Text -> Text+toBookmarkName s+  | Just (c, _) <- T.uncons s+  , isLetter c+  , T.length s <= 40 = s+  | otherwise = T.pack $ 'X' : drop 1 (showDigest (sha1 (fromTextLazy $ TL.fromStrict s)))++maxListLevel :: Int+maxListLevel = 8++convertSpace :: [Inline] -> [Inline]+convertSpace (Str x : Space : Str y : xs) = convertSpace (Str (x <> " " <> y) : xs)+convertSpace (Str x : Str y : xs)         = convertSpace (Str (x <> y) : xs)+convertSpace (x:xs)                       = x : convertSpace xs+convertSpace []                           = []
src/Text/Pandoc/Writers/Docx/Table.hs view
@@ -159,7 +159,7 @@   AlignLeft    -> "left"   AlignRight   -> "right"   AlignCenter  -> "center"-  AlignDefault -> "left"+  AlignDefault -> ""  tableLayout :: [ColSpec] -> ([Element], [(Text, Text)]) tableLayout specs =@@ -253,7 +253,7 @@       , mknode "w:p" [] [mknode "w:pPr" [] ()]]   OOXMLCell _attr align rowspan (ColSpan colspan) contents -> do     compactStyle <- pStyleM "Compact"-    es <- withParaProp (alignmentFor align) $ blocksToOpenXML contents+    es <- maybe id withParaProp (alignmentFor align) $ blocksToOpenXML contents     -- Table cells require a <w:p> element, even an empty one!     -- Not in the spec but in Word 2007, 2010. See #4953. And     -- apparently the last element must be a <w:p>, see #6983.@@ -271,5 +271,6 @@              e:_   | qName (elName e) == "p" -> es              _ -> es ++ [Elem $ mknode "w:p" [] ()] -alignmentFor :: Alignment -> Element-alignmentFor al = mknode "w:jc" [("w:val",alignmentToString al)] ()+alignmentFor :: Alignment -> Maybe Element+alignmentFor AlignDefault = Nothing+alignmentFor al = Just $ mknode "w:jc" [("w:val",alignmentToString al)] ()
src/Text/Pandoc/Writers/Docx/Types.hs view
@@ -40,12 +40,15 @@  data ListMarker = NoMarker                 | BulletMarker+                | CheckboxMarker Bool                 | NumberMarker ListNumberStyle ListNumberDelim Int                 deriving (Show, Read, Eq, Ord)  listMarkerToId :: ListMarker -> Text listMarkerToId NoMarker = "990" listMarkerToId BulletMarker = "991"+listMarkerToId (CheckboxMarker False) = "992"+listMarkerToId (CheckboxMarker True) = "993" listMarkerToId (NumberMarker sty delim n) = T.pack $   '9' : '9' : styNum : delimNum : show n   where styNum = case sty of
src/Text/Pandoc/Writers/HTML.hs view
@@ -34,7 +34,7 @@     ( StateT, MonadState(get), gets, modify, evalStateT ) import Control.Monad ( liftM, when, foldM, unless ) import Control.Monad.Trans ( MonadTrans(lift) )-import Data.Char (ord)+import Data.Char (ord, isSpace, isAscii) import Data.List (intercalate, intersperse, partition, delete, (\\), foldl') import Data.List.NonEmpty (NonEmpty((:|))) import Data.Containers.ListUtils (nubOrd)@@ -43,7 +43,8 @@ import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.Lazy as TL-import Network.URI (URI (..), parseURIReference)+import Network.URI (URI (..), parseURIReference, escapeURIString)+import Text.Pandoc.URI (urlEncode) import Numeric (showHex) import Text.DocLayout (render, literal, Doc) import Text.Blaze.Internal (MarkupM (Empty), customLeaf, customParent)@@ -61,7 +62,6 @@ import Text.Pandoc.Writers.Math import Text.Pandoc.Writers.Shared import qualified Text.Pandoc.Writers.AnnotatedTable as Ann-import Text.Pandoc.URI (urlEncode) import Text.Pandoc.XML (escapeStringForXML, fromEntities, toEntities,                         html5Attributes, html4Attributes, rdfaAttributes) import qualified Text.Blaze.XHtml5 as H5@@ -308,12 +308,13 @@         modify (\st' -> st'{ stNotes = mempty, stEmittedNotes = stEmittedNotes st' + length (stNotes st') })         return notes   st <- get+  let html5 = stHtml5 st   let thebody = blocks' >> notes   let math = layoutMarkup $ case writerHTMLMathMethod opts of         MathJax url           | slideVariant /= RevealJsSlides ->           -- mathjax is handled via a special plugin in revealjs-            H.script ! A.src (toValue url)+            H.script ! A.src (toValue $ toURI html5 url)                     ! A.type_ "text/javascript"                     $ case slideVariant of                             SlideousSlides ->@@ -323,7 +324,7 @@         KaTeX url -> do           H.script !             A.defer mempty !-            A.src (toValue $ url <> "katex.min.js") $ mempty+            A.src (toValue $ toURI html5 $ url <> "katex.min.js") $ mempty           nl           let katexFlushLeft =                 case lookupContext "classoption" metadata of@@ -346,7 +347,7 @@             ]           nl           H.link ! A.rel "stylesheet" !-            A.href (toValue $ url <> "katex.min.css")+            A.href (toValue $ toURI html5 url <> "katex.min.css")          _ -> mempty   let mCss :: Maybe [Text] = lookupContext "css" metadata@@ -482,21 +483,13 @@         => WriterOptions -> [Html] -> StateT WriterState m Html defList opts items = toList H.dl opts (items ++ [nl]) -isTaskListItem :: [Block] -> Bool-isTaskListItem (Plain (Str "☐":Space:_):_) = True-isTaskListItem (Plain (Str "☒":Space:_):_) = True-isTaskListItem (Para  (Str "☐":Space:_):_) = True-isTaskListItem (Para  (Str "☒":Space:_):_) = True-isTaskListItem _                           = False- listItemToHtml :: PandocMonad m                => WriterOptions -> [Block] -> StateT WriterState m Html-listItemToHtml opts bls-  | Plain (Str "☐":Space:is) : bs <- bls = taskListItem False id  is bs-  | Plain (Str "☒":Space:is) : bs <- bls = taskListItem True  id  is bs-  | Para  (Str "☐":Space:is) : bs <- bls = taskListItem False H.p is bs-  | Para  (Str "☒":Space:is) : bs <- bls = taskListItem True  H.p is bs-  | otherwise = blockListToHtml opts bls+listItemToHtml opts bls =+  case toTaskListItem bls of+    Just (checked, (Para is:bs)) -> taskListItem checked H.p is bs+    Just (checked, (Plain is:bs)) -> taskListItem checked id is bs+    _ -> blockListToHtml opts bls   where     taskListItem checked constr is bs = do       let checkbox  = if checked@@ -601,12 +594,14 @@ obfuscateLink :: PandocMonad m               => WriterOptions -> Attr -> Html -> Text               -> StateT WriterState m Html-obfuscateLink opts attr txt s | writerEmailObfuscation opts == NoObfuscation =-  addAttrs opts attr $ H.a ! A.href (toValue s) $ txt-obfuscateLink opts attr (TL.toStrict . renderHtml -> txt) s =+obfuscateLink opts attr txt s | writerEmailObfuscation opts == NoObfuscation = do+  html5 <- gets stHtml5+  addAttrs opts attr $ H.a ! A.href (toValue $ toURI html5 s) $ txt+obfuscateLink opts attr (TL.toStrict . renderHtml -> txt) s = do+  html5 <- gets stHtml5   let meth = writerEmailObfuscation opts-      s' = T.toLower (T.take 7 s) <> T.drop 7 s-  in  case parseMailto s' of+  let s' = T.toLower (T.take 7 s) <> T.drop 7 s+  case parseMailto s' of         (Just (name', domain)) ->           let domain'  = T.replace "." " dot " domain               at'      = obfuscateChar '@'@@ -634,7 +629,8 @@                      linkText  <> "+'<\\/'+'a'+'>');\n// -->\n")) >>                      H.noscript (preEscapedText $ obfuscateString altText)                 _ -> throwError $ PandocSomeError $ "Unknown obfuscation method: " <> tshow meth-        _ -> addAttrs opts attr $ H.a ! A.href (toValue s) $ toHtml txt  -- malformed email+        _ -> addAttrs opts attr $ H.a ! A.href (toValue $ toURI html5 s)+                                      $ toHtml txt  -- malformed email  -- | Obfuscate character as entity. obfuscateChar :: Char -> Text@@ -1019,8 +1015,7 @@               _ -> H.p  contents' blockToHtmlInner opts (BulletList lst) = do   contents <- mapM (listItemToHtml opts) lst-  let isTaskList = not (null lst) && all isTaskListItem lst-  (if isTaskList then (! A.class_ "task-list") else id) <$>+  (if isJust (mapM toTaskListItem lst) then (! A.class_ "task-list") else id) <$>     unordList opts contents blockToHtmlInner opts (OrderedList (startnum, numstyle, _) lst) = do   contents <- mapM (listItemToHtml opts) lst@@ -1272,19 +1267,13 @@                => WriterOptions                -> TableRow                -> StateT WriterState m Html-tableRowToHtml opts (TableRow tblpart attr rownum rowhead rowbody) = do-  let rowclass = case rownum of-        Ann.RowNumber x | x `rem` 2 == 1   -> "odd"-        _               | tblpart /= Thead -> "even"-        _                                  -> "header"-  let attr' = case attr of-                (id', classes, rest) -> (id', rowclass:classes, rest)+tableRowToHtml opts (TableRow tblpart attr _rownum rowhead rowbody) = do   let celltype = case tblpart of                    Thead -> HeaderCell                    _     -> BodyCell   headcells <- mapM (cellToHtml opts HeaderCell) rowhead   bodycells <- mapM (cellToHtml opts celltype) rowbody-  rowHtml <- addAttrs opts attr' $ H.tr $ do+  rowHtml <- addAttrs opts attr $ H.tr $ do     nl     mconcat headcells     mconcat bodycells@@ -1503,8 +1492,7 @@                            InlineMath  -> "\\textstyle "                            DisplayMath -> "\\displaystyle "               return $ imtag ! A.style "vertical-align:middle"-                             ! A.src (toValue . (url <>) .-                                 urlEncode $ s <> str')+                             ! A.src (toValue . (url <>) . urlEncode $ s <> str')                              ! A.alt (toValue str')                              ! A.title (toValue str')                              ! A.class_ mathClass@@ -1566,7 +1554,8 @@                                                              else writerIdentifierPrefix opts                                              in  "#" <> prefix <> xs                                    _ -> s-                        let link = H.a ! A.href (toValue s') $ linkText+                        let link = H.a ! A.href (toValue $ toURI html5 s')+                                       $ linkText                         link' <- addAttrs opts (ident, classes, kvs) link                         return $ if T.null tit                                     then link'@@ -1581,7 +1570,7 @@                               -- reveal.js uses data-src for lazy loading                               (if isReveal                                   then customAttribute "data-src" $ toValue s-                                  else A.src $ toValue s) :+                                  else A.src $ toValue $ toURI html5 s) :                               [A.title $ toValue tit | not (T.null tit)] ++                               attrs                             imageTag = (if html5 then H5.img else H.img@@ -1592,7 +1581,8 @@                               let linkTxt = if null txt                                             then fallbackTxt                                             else alternate-                              in (tg $ H.a ! A.href (toValue s) $ toHtml linkTxt+                              in (tg $ H.a ! A.href (toValue $ toURI html5 s)+                                           $ toHtml linkTxt                                  , [A5.controls ""] )                             s' = fromMaybe s $ T.stripSuffix ".gz" s                             normSrc = maybe (T.unpack s) uriPath (parseURIReference $ T.unpack s')@@ -1615,7 +1605,7 @@                         modify $ \st -> st {stNotes = htmlContents:notes}                         slideVariant <- gets stSlideVariant                         let revealSlash = T.pack ['/' | slideVariant == RevealJsSlides]-                        let link = H.a ! A.href (toValue $ "#" <>+                        let link = H.a ! A.href (toValue $ toURI html5 $ "#" <>                                          revealSlash <>                                          writerIdentifierPrefix opts <> "fn" <> ref)                                        ! A.class_ "footnote-ref"@@ -1775,3 +1765,9 @@  where   go (Link attr ils _) = Span attr ils   go x = x++toURI :: Bool -> Text -> Text+toURI isHtml5 t = if isHtml5 then t else escapeURI t+ where+   escapeURI = T.pack . escapeURIString (not . needsEscaping) . T.unpack+   needsEscaping c = isSpace c || T.any (== c) "<>|\"{}[]^`" || not (isAscii c)
src/Text/Pandoc/Writers/LaTeX.hs view
@@ -33,13 +33,14 @@ import Data.Containers.ListUtils (nubOrd) import Data.Char (isDigit) import Data.List (intersperse, (\\))-import Data.Maybe (catMaybes, fromMaybe, isJust, mapMaybe, isNothing)+import Data.Maybe (catMaybes, fromMaybe, isJust, mapMaybe, isNothing,+                   maybeToList) import Data.Monoid (Any (..)) import Data.Text (Text) import qualified Data.Text as T import Network.URI (unEscapeString) import Text.DocTemplates (FromContext(lookupContext), renderTemplate)-import Text.Collate.Lang (renderLang)+import Text.Collate.Lang (renderLang, Lang(langLanguage)) import Text.Pandoc.Class.PandocMonad (PandocMonad, report, toLang) import Text.Pandoc.Definition import Text.Pandoc.Highlighting (formatLaTeXBlock, formatLaTeXInline, highlight,@@ -262,6 +263,11 @@              (map literal                (nubOrd . catMaybes . filter (/= babelLang)                 $ map toBabel docLangs))+        $ defField "selnolig-langs"+             (literal . T.intercalate "," $+               let langs = docLangs ++ maybeToList mblang+               in (["english" | any ((== "en") . langLanguage) langs] +++                   ["german" | any ((== "de") . langLanguage) langs]))         $ defField "latex-dir-rtl"            ((render Nothing <$> getField "dir" context) ==                Just ("rtl" :: Text)) context@@ -513,7 +519,7 @@   isFirstInDefinition <- gets stIsFirstInDefinition   beamer <- gets stBeamer   let inc = if beamer && incremental then "[<+->]" else ""-  items <- mapM listItemToLaTeX lst+  items <- mapM (listItemToLaTeX False) lst   let spacing = if isTightList lst                    then text "\\tightlist"                    else empty@@ -530,7 +536,7 @@   let oldlevel = stOLLevel st   isFirstInDefinition <- gets stIsFirstInDefinition   put $ st {stOLLevel = oldlevel + 1}-  items <- mapM listItemToLaTeX lst+  items <- mapM (listItemToLaTeX True) lst   modify (\s -> s {stOLLevel = oldlevel})   let beamer = stBeamer st   let tostyle x = case numstyle of@@ -653,27 +659,27 @@ blockListToLaTeX lst =   vsep `fmap` mapM (\b -> setEmptyLine True >> blockToLaTeX b) lst -listItemToLaTeX :: PandocMonad m => [Block] -> LW m (Doc Text)-listItemToLaTeX lst+listItemToLaTeX :: PandocMonad m => Bool -> [Block] -> LW m (Doc Text)+listItemToLaTeX isOrdered lst   -- we need to put some text before a header if it's the first   -- element in an item. This will look ugly in LaTeX regardless, but   -- this will keep the typesetter from throwing an error.   | (Header{} :_) <- lst =     (text "\\item ~" $$) . nest 2 <$> blockListToLaTeX lst-  | Plain (Str "☐":Space:is) : bs <- lst = taskListItem False is bs-  | Plain (Str "☒":Space:is) : bs <- lst = taskListItem True  is bs-  | Para  (Str "☐":Space:is) : bs <- lst = taskListItem False is bs-  | Para  (Str "☒":Space:is) : bs <- lst = taskListItem True  is bs+  | not isOrdered+  , Just (checked, bs) <- toTaskListItem lst+   = taskListItem checked bs   | otherwise = (text "\\item" $$) . nest 2 <$> blockListToLaTeX lst   where-    taskListItem checked is bs = do+    taskListItem checked bs = do       let checkbox  = if checked                       then "$\\boxtimes$"                       else "$\\square$"-      isContents <- inlineListToLaTeX is-      bsContents <- blockListToLaTeX bs-      return $ "\\item" <> brackets checkbox-        $$ nest 2 (isContents $+$ bsContents)+      let bs' = case bs of+                  Plain ils : xs -> Para ils : xs+                  _ -> bs+      bsContents <- blockListToLaTeX bs'+      return $ "\\item" <> brackets checkbox $$ nest 2 bsContents  defListItemToLaTeX :: PandocMonad m => ([Inline], [[Block]]) -> LW m (Doc Text) defListItemToLaTeX (term, defs) = do@@ -1068,7 +1074,7 @@                          Just (Percent a) ->                            [d <> literal (showFl (a / 100)) <>                              case dir of-                                Width  -> "\\textwidth"+                                Width  -> "\\linewidth"                                 Height -> "\\textheight"                            ]                          Just dim         ->@@ -1076,11 +1082,14 @@                          Nothing          ->                            case dir of                                 Width | isJust (dimension Height attr) ->-                                  [d <> "\\textwidth"]+                                  [d <> "\\linewidth"]                                 Height | isJust (dimension Width attr) ->                                   [d <> "\\textheight"]                                 _ -> []       optList = showDim Width <> showDim Height <>+                (case (dimension Height attr, dimension Width attr) of+                  (Just _, Just _) -> []+                  _ -> ["keepaspectratio"]) <>                 maybe [] (\x -> ["page=" <> literal x]) (lookup "page" kvs) <>                 maybe [] (\x -> ["trim=" <> literal x]) (lookup "trim" kvs) <>                 maybe [] (const ["clip"]) (lookup "clip" kvs)@@ -1094,8 +1103,11 @@   inHeading <- gets stInHeading   return $     (if inHeading then "\\protect" else "") <>-      (if isSVG then "\\includesvg" else "\\includegraphics") <>-    options <> braces (literal source'')+    (case dimension Width attr `mplus` dimension Height attr of+       Just _ -> id+       Nothing -> ("\\pandocbounded" <>) . braces)+      ((if isSVG then "\\includesvg" else "\\includegraphics") <>+        options <> braces (literal source'')) inlineToLaTeX (Note contents) = do   setEmptyLine False   externalNotes <- gets stExternalNotes
src/Text/Pandoc/Writers/LaTeX/Table.hs view
@@ -149,7 +149,7 @@     toColDescriptor :: Int -> Alignment -> Double -> Text     toColDescriptor numcols align width =       T.pack $ printf-      ">{%s\\arraybackslash}p{(\\columnwidth - %d\\tabcolsep) * \\real{%0.4f}}"+      ">{%s\\arraybackslash}p{(\\linewidth - %d\\tabcolsep) * \\real{%0.4f}}"       (T.unpack (alignCommand align))       ((numcols - 1) * 2)       width@@ -391,7 +391,7 @@               (T.unpack (colAlign align))               (if colnum + colspan >= numcols then skipColSep else "") -        else printf "%s>{%s\\arraybackslash}p{(\\columnwidth - %d\\tabcolsep) * \\real{%0.4f} + %d\\tabcolsep}%s"+        else printf "%s>{%s\\arraybackslash}p{(\\linewidth - %d\\tabcolsep) * \\real{%0.4f} + %d\\tabcolsep}%s"               (if colnum == 0 then skipColSep else "")               (T.unpack (alignCommand align))               (2 * (numcols - 1))
src/Text/Pandoc/Writers/LaTeX/Util.hs view
@@ -235,7 +235,7 @@                                w = maybe "0.48" fromPct (lookup "width" kvs)                            in  inCmd "begin" "column" <>                                valign <>-                               braces (literal w <> "\\textwidth")+                               braces (literal w <> "\\linewidth")                                $$ contents                                $$ inCmd "end" "column"                     else id
src/Text/Pandoc/Writers/Markdown.hs view
@@ -466,9 +466,9 @@       | f == "plain" -> return $ literal str <> literal "\n"     Commonmark       | f `elem` ["gfm", "commonmark", "commonmark_x", "markdown"]-         -> return $ literal str <> literal "\n"+         -> return $ literal str $$ blankline       | f `elem` ["html", "html5", "html4"]-         -> return $ literal (removeBlankLinesInHTML str) <> literal "\n"+         -> return $ literal (removeBlankLinesInHTML str) $$ blankline     Markdown       | f `elem` ["markdown", "markdown_github", "markdown_phpextra",                   "markdown_mmd", "markdown_strict"]@@ -592,7 +592,7 @@         | variant == PlainText = "  "         | otherwise            = "> "   contents <- blockListToMarkdown opts blocks-  return $ prefixed leader contents <> blankline+  return $ text leader <> prefixed leader contents <> blankline blockToMarkdown' opts t@(Table (ident,_,_) blkCapt specs thead tbody tfoot) = do   let (caption, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot   let numcols = maximum (length aligns :| length widths :@@ -716,7 +716,10 @@       -- fallback to raw html if possible or div otherwise       if isEnabled Ext_raw_html opts       then figureToMarkdown opts figattr capt body-      else blockToMarkdown' opts $ figureDiv figattr capt body+      else if (isEnabled Ext_fenced_divs opts || isEnabled Ext_native_divs opts) ||+                  not (isEnabled Ext_implicit_figures opts)+              then blockToMarkdown' opts $ figureDiv figattr capt body+              else blockListToMarkdown opts body  inList :: Monad m => MD m a -> MD m a inList p = local (\env -> env {envInList = True}) p
src/Text/Pandoc/Writers/Shared.hs view
@@ -45,11 +45,12 @@                      , ensureValidXmlIdentifiers                      , setupTranslations                      , isOrderedListMarker+                     , toTaskListItem                      ) where import Safe (lastMay) import qualified Data.ByteString.Lazy as BL-import Control.Monad (zipWithM)+import Control.Monad (zipWithM, MonadPlus, mzero) import Data.Either (isRight) import Data.Aeson (ToJSON (..), encode) import Data.Char (chr, ord, isSpace, isLetter, isUpper)@@ -636,3 +637,10 @@ isOrderedListMarker xs = not (T.null xs) && (T.last xs `elem` ['.',')']) &&               isRight (runParser (anyOrderedListMarker >> eof)                        defaultParserState "" xs)++toTaskListItem :: MonadPlus m => [Block] -> m (Bool, [Block])+toTaskListItem (Plain (Str "☐":Space:ils):xs) = pure (False, Plain ils:xs)+toTaskListItem (Plain (Str "☒":Space:ils):xs) = pure (True, Plain ils:xs)+toTaskListItem (Para  (Str "☐":Space:ils):xs) = pure (False, Para ils:xs)+toTaskListItem (Para  (Str "☒":Space:ils):xs) = pure (True, Para ils:xs)+toTaskListItem _                              = mzero
src/Text/Pandoc/Writers/Texinfo.hs view
@@ -12,7 +12,7 @@ Conversion of 'Pandoc' format into Texinfo. -} module Text.Pandoc.Writers.Texinfo ( writeTexinfo ) where-import Control.Monad (zipWithM)+import Control.Monad (zipWithM, unless) import Control.Monad.Except (throwError) import Control.Monad.State.Strict     ( StateT, MonadState(get), gets, modify, evalStateT )@@ -20,13 +20,14 @@ import Data.List (maximumBy, transpose, foldl') import Data.List.NonEmpty (nonEmpty) import Data.Ord (comparing)-import qualified Data.Set as Set+import qualified Data.Map as M import Data.Text (Text) import qualified Data.Text as T import Network.URI (unEscapeString) import System.FilePath import Text.Pandoc.Class.PandocMonad (PandocMonad, report) import Text.Pandoc.Definition+import Text.Pandoc.Walk (walkM) import Text.Pandoc.Error import Text.Pandoc.ImageSize import Text.Pandoc.Logging@@ -40,11 +41,26 @@  data WriterState =   WriterState { stStrikeout   :: Bool  -- document contains strikeout-              , stEscapeComma :: Bool -- in a context where we need @comma-              , stIdentifiers :: Set.Set Text -- header ids used already+              , stContext     :: Context+              , stNodes       :: M.Map Text Int -- maps node to number of duplicates+              , stHeadings    :: M.Map Text Text -- header ids to node texts               , stOptions     :: WriterOptions -- writer options               } +data Context = NormalContext | NodeContext+  deriving (Eq, Show)++withContext :: PandocMonad m => Context -> TI m a -> TI m a+withContext context pa = do+  oldContext <- gets stContext+  modify $ \s -> s{ stContext = context }+  res <- pa+  modify $ \s -> s{ stContext = oldContext }+  pure res++disallowedInNode :: Char -> Bool+disallowedInNode c = c `elem` ['.',':',',','(',')']+ {- TODO:  - internal cross references a la HTML  - generated .texi files don't work when run through texi2dvi@@ -56,16 +72,36 @@ writeTexinfo :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeTexinfo options document =   evalStateT (pandocToTexinfo options $ wrapTop document)-  WriterState { stStrikeout = False, stEscapeComma = False,-                stIdentifiers = Set.empty, stOptions = options}+  WriterState { stStrikeout = False,+                stContext = NormalContext,+                stNodes = mempty,+                stHeadings = mempty,+                stOptions = options}  -- | Add a "Top" node around the document, needed by Texinfo. wrapTop :: Pandoc -> Pandoc wrapTop (Pandoc meta blocks) =   Pandoc meta (Header 0 nullAttr (docTitle meta) : blocks) +addNodeText :: PandocMonad m => Block -> TI m Block+addNodeText (Header lev (ident,_,_) ils) | lev >= 1 && lev <= 4 = do+  node <- render Nothing <$> withContext NodeContext (inlineListToTexinfo ils)+  nodes <- gets stNodes+  node' <- case M.lookup node nodes of+                Just i -> do+                  modify $ \st -> st{ stNodes = M.adjust (+ 1) node nodes }+                  pure $ node <> " " <> tshow (i + 1)+                Nothing -> do+                  modify $ \st -> st{ stNodes = M.insert node 1 nodes }+                  pure node+  unless (T.null ident) $+    modify $ \st -> st{ stHeadings = M.insert ident node' (stHeadings st) }+  pure $ Header lev (ident,[],[("node", node')]) ils+addNodeText x = pure  x+ pandocToTexinfo :: PandocMonad m => WriterOptions -> Pandoc -> TI m Text-pandocToTexinfo options (Pandoc meta blocks) = do+pandocToTexinfo options (Pandoc meta blocks') = do+  blocks <- walkM addNodeText blocks'   let titlePage = not $ all null                       $ docTitle meta : docDate meta : docAuthors meta   let colwidth = if writerWrapText options == WrapAuto@@ -87,27 +123,26 @@        Just tpl -> renderTemplate tpl context  -- | Escape things as needed for Texinfo.-stringToTexinfo :: Text -> Text+stringToTexinfo :: PandocMonad m => Text -> TI m Text stringToTexinfo t-  | T.all isAlphaNum t = t-  | otherwise = T.concatMap escChar t-  where escChar '{'      = "@{"-        escChar '}'      = "@}"-        escChar '@'      = "@@"-        escChar '\160'   = "@ "-        escChar '\x2014' = "---"-        escChar '\x2013' = "--"-        escChar '\x2026' = "@dots{}"-        escChar '\x2019' = "'"-        escChar c        = T.singleton c--escapeCommas :: PandocMonad m => TI m (Doc Text) -> TI m (Doc Text)-escapeCommas parser = do-  oldEscapeComma <- gets stEscapeComma-  modify $ \st -> st{ stEscapeComma = True }-  res <- parser-  modify $ \st -> st{ stEscapeComma = oldEscapeComma }-  return res+  | T.all isAlphaNum t = pure t+  | otherwise = do+      context <- gets stContext+      let escChar '{'      = "@{"+          escChar '}'      = "@}"+          escChar '@'      = "@@"+          escChar '\160'   = "@ "+          escChar '\x2014' = "---"+          escChar '\x2013' = "--"+          escChar '\x2026' = "@dots{}"+          escChar '\x2019' = "'"+          escChar ',' | context == NodeContext = ""+          escChar ':' | context == NodeContext = ""+          escChar '.' | context == NodeContext = ""+          escChar '(' | context == NodeContext = ""+          escChar ')' | context == NodeContext = ""+          escChar c        = T.singleton c+      pure $ T.concatMap escChar t  -- | Puts contents into Texinfo command. inCmd :: Text -> Doc Text -> Doc Text@@ -197,22 +232,12 @@   return $ text "@node Top" $$            text "@top " <> txt <> blankline -blockToTexinfo (Header level (ident,_,_) lst)-  | level < 1 || level > 4 = blockToTexinfo (Para lst)-  | otherwise = do-    node <- inlineListForNode lst+blockToTexinfo (Header level (_,_,[("node",node)]) lst) = do     txt <- inlineListToTexinfo lst-    idsUsed <- gets stIdentifiers-    opts <- gets stOptions-    let id' = if T.null ident-                 then uniqueIdent (writerExtensions opts) lst idsUsed-                 else ident-    modify $ \st -> st{ stIdentifiers = Set.insert id' idsUsed }     sec <- seccmd level     return $ if (level > 0) && (level <= 4)-                then blankline <> text "@node " <> node $$-                     literal sec <> txt $$-                     text "@anchor" <> braces (literal $ "#" <> id')+                then blankline <> text "@node " <> literal node $$+                     literal sec <> txt                 else txt     where       seccmd :: PandocMonad m => Int -> TI m Text@@ -222,6 +247,9 @@       seccmd 4 = return "@subsubsection "       seccmd _ = throwError $ PandocSomeError "illegal seccmd level" +-- non-node header:+blockToTexinfo (Header _ _ lst) = blockToTexinfo (Para lst)+ blockToTexinfo (Table _ blkCapt specs thead tbody tfoot) = do   let (caption, aligns, widths, heads, rows) = toLegacyTable blkCapt specs thead tbody tfoot   headers <- if all null heads@@ -359,19 +387,23 @@ collectNodes _ [] = [] collectNodes level (x:xs) =   case x of-    (Header hl _ _) | hl < level -> []-                    | hl == level -> x : collectNodes level xs-                    | otherwise -> collectNodes level xs+    (Header hl _ _)+      | hl < level -> []+      | hl == level -> x : collectNodes level xs+      | otherwise -> collectNodes level xs     _ ->       collectNodes level xs  makeMenuLine :: PandocMonad m              => Block              -> TI m (Doc Text)-makeMenuLine (Header _ _ lst) = do-  txt <- inlineListForNode lst-  return $ text "* " <> txt <> text "::"-makeMenuLine _ = throwError $ PandocSomeError "makeMenuLine called with non-Header block"+makeMenuLine (Header _ (_,_,[("node", node)]) lst) = do+  txt <- withContext NodeContext $ inlineListToTexinfo lst+  pure $ nowrap $ text "* " <>+    if render Nothing txt == node+       then literal node <> "::"+       else txt <> ": " <> literal node <> "."+makeMenuLine _ = throwError $ PandocSomeError "makeMenuLine called with non-node"  listItemToTexinfo :: PandocMonad m                   => [Block]@@ -401,17 +433,6 @@                     -> TI m (Doc Text) inlineListToTexinfo lst = hcat <$> mapM inlineToTexinfo lst --- | Convert list of inline elements to Texinfo acceptable for a node name.-inlineListForNode :: PandocMonad m-                  => [Inline]  -- ^ Inlines to convert-                  -> TI m (Doc Text)-inlineListForNode = return . literal . stringToTexinfo .-                    T.filter (not . disallowedInNode) . stringify---- periods, commas, colons, and parentheses are disallowed in node names-disallowedInNode :: Char -> Bool-disallowedInNode c = c `elem` (".,:()" :: String)- -- | Convert inline element to Texinfo inlineToTexinfo :: PandocMonad m                 => Inline    -- ^ Inline to convert@@ -446,11 +467,13 @@ inlineToTexinfo (SmallCaps lst) =   inCmd "sc" <$> inlineListToTexinfo lst -inlineToTexinfo (Code (_, cls , _) str) | T.pack "variable" `elem` cls  =-  return $ literal $ "@code{@var{" <> stringToTexinfo str <> "}}"+inlineToTexinfo (Code (_, cls , _) str) | T.pack "variable" `elem` cls  = do+  code <- stringToTexinfo str+  return $ literal $ "@code{@var{" <> code <> "}}" -inlineToTexinfo (Code _ str) =-  return $ literal $ "@code{" <> stringToTexinfo str <> "}"+inlineToTexinfo (Code _ str) = do+  code <- stringToTexinfo str+  return $ literal $ "@code{" <> code <> "}"  inlineToTexinfo (Quoted SingleQuote lst) = do   contents <- inlineListToTexinfo lst@@ -462,7 +485,7 @@  inlineToTexinfo (Cite _ lst) =   inlineListToTexinfo lst-inlineToTexinfo (Str str) = return $ literal (stringToTexinfo str)+inlineToTexinfo (Str str) = literal <$> stringToTexinfo str inlineToTexinfo (Math _ str) = return $ inCmd "math" $ literal str inlineToTexinfo il@(RawInline f str)   | f == "latex" || f == "tex" =@@ -481,21 +504,28 @@ inlineToTexinfo Space = return space  inlineToTexinfo (Link _ txt (src, _))-  | Just ('#', _) <- T.uncons src = do-      contents <- escapeCommas $ inlineListToTexinfo txt-      return $ text "@ref" <>-        braces (literal (stringToTexinfo src) <> text "," <> contents)+  | Just ('#', ident) <- T.uncons src = do+      headings <- gets stHeadings+      target <- case M.lookup ident headings of+                  Nothing -> literal <$> stringToTexinfo+                                    (T.filter (not . disallowedInNode) src)+                  Just node -> pure $ literal node+      contents <- withContext NodeContext $ inlineListToTexinfo txt+      return $ text "@ref"+        <> braces (target <> if contents == target+                                then mempty+                                else text ",," <> contents)   | otherwise = case txt of       [Str x] | escapeURI x == src ->  -- autolink                   return $ literal $ "@url{" <> x <> "}"       _ -> do-        contents <- escapeCommas $ inlineListToTexinfo txt-        let src1 = stringToTexinfo src+        contents <- withContext NodeContext $ inlineListToTexinfo txt+        src1 <- stringToTexinfo src         return $ literal ("@uref{" <> src1 <> ",") <> contents <>                  char '}'  inlineToTexinfo (Image attr alternate (source, _)) = do-  content <- escapeCommas $ inlineListToTexinfo alternate+  content <- withContext NodeContext $ inlineListToTexinfo alternate   opts <- gets stOptions   let showDim dim = case dimension dim attr of                       (Just (Pixel a))   -> showInInch opts (Pixel a) <> "in"
src/Text/Pandoc/Writers/Textile.hs view
@@ -337,14 +337,10 @@                   -> TW m Text tableRowToTextile opts alignStrings rownum cols' = do   let celltype = if rownum == 0 then "th" else "td"-  let rowclass = case rownum of-                      0 -> "header"-                      x | x `rem` 2 == 1 -> "odd"-                      _ -> "even"   cols'' <- zipWithM             (\alignment item -> tableItemToTextile opts celltype alignment item)             alignStrings cols'-  return $ "<tr class=\"" <> rowclass <> "\">\n" <> T.unlines cols'' <> "</tr>"+  return $ "<tr>\n" <> T.unlines cols'' <> "</tr>"  alignmentToText :: Alignment -> Text alignmentToText alignment = case alignment of
src/Text/Pandoc/Writers/Typst.hs view
@@ -37,6 +37,7 @@ import Text.Collate.Lang (Lang(..), parseLang) import Text.Printf (printf) import Data.Char (isAlphaNum)+import Data.Maybe (fromMaybe)  -- | Convert Pandoc to Typst. writeTypst :: PandocMonad m => WriterOptions -> Pandoc -> m Text@@ -195,13 +196,14 @@                    else vsep items') $$ blankline     DefinitionList items ->       ($$ blankline) . vsep <$> mapM defListItemToTypst items-    Table (ident,_,tabkvs) (Caption _ caption) colspecs thead tbodies tfoot -> do+    Table (ident,tabclasses,tabkvs) (Caption _ caption) colspecs thead tbodies tfoot -> do       let lab = toLabel FreestandingLabel ident       capt' <- if null caption                   then return mempty                   else do                     captcontents <- blocksToTypst caption                     return $ ", caption: " <> brackets captcontents+      let typstFigureKind = literal (", kind: " <> fromMaybe "table" (lookup "typst:figure:kind" tabkvs))       let numcols = length colspecs       let (aligns, widths) = unzip colspecs       let commaSep = hcat . intersperse ", "@@ -273,25 +275,27 @@       header <- fromHead thead       footer <- fromFoot tfoot       body <- vcat <$> mapM fromTableBody tbodies-      return $-        "#figure("-        $$-        nest 2-         ("align(center)[" <> toTypstSetText typstTextAttrs <> "#table("-          $$ nest 2-             (  "columns: " <> columns <> ","-             $$ "align: " <> alignarray <> ","-             $$ toTypstPropsListTerm typstAttrs-             $$ header-             $$ body-             $$ footer-             )-          $$ ")]"-          $$ capt'-          $$ ", kind: table"-          $$ ")")-        $$ lab-        $$ blankline+      let table = toTypstSetText typstTextAttrs <> "#table("+            $$ nest 2+                (  "columns: " <> columns <> ","+                $$ "align: " <> alignarray <> ","+                $$ toTypstPropsListTerm typstAttrs+                $$ header+                $$ body+                $$ footer+            )+            $$ ")"+      return $ if "typst:no-figure" `elem` tabclasses+        then table+        else "#figure("+            $$+            nest 2+            ("align(center)[" <> table <> "]"+              $$ capt'+              $$ typstFigureKind+              $$ ")")+            $$ lab+          $$ blankline     Figure (ident,_,_) (Caption _mbshort capt) blocks -> do       caption <- blocksToTypst capt       contents <- case blocks of
test/Tests/Readers/Docx.hs view
@@ -302,6 +302,10 @@             "docx/definition_list.docx"             "docx/definition_list.native"           , testCompare+            "task lists"+            "docx/task_list.docx"+            "docx/task_list.native"+          , testCompare             "custom defined lists in styles"             "docx/german_styled_lists.docx"             "docx/german_styled_lists.native"
test/Tests/Writers/Docx.hs view
@@ -98,6 +98,11 @@             "docx/definition_list.native"             "docx/golden/definition_list.docx"           , docxTest+            "task lists"+            def+            "docx/task_list.native"+            "docx/golden/task_list.docx"+          , docxTest             "footnotes and endnotes"             def             "docx/notes.native"
test/Tests/Writers/LaTeX.hs view
@@ -70,7 +70,7 @@             "\\begin{description}\n\\item[foo] ~ \n\\subsection{bar}\n\nbaz\n\\end{description}"           , "containing image" =:             header 1 (image "imgs/foo.jpg" "" (text "Alt text")) =?>-            "\\section{\\texorpdfstring{\\protect\\includegraphics{imgs/foo.jpg}}{Alt text}}"+            "\\section{\\texorpdfstring{\\protect\\pandocbounded{\\includegraphics[keepaspectratio]{imgs/foo.jpg}}}{Alt text}}"           ]         , testGroup "inline code"           [ "struck out and highlighted" =:
test/command/1166.md view
@@ -17,28 +17,28 @@ ^D <table> <thead>-<tr class="header">+<tr> <th>col 1</th> <th>col 2</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>1</td> <td>Second column of row 1.</td> </tr>-<tr class="even">+<tr> <td><p>2</p></td> <td><p>Second column of row 2. Second line of paragraph.</p></td> </tr>-<tr class="odd">+<tr> <td><p>3</p></td> <td><ul> <li>Second column of row 3.</li> <li>Second item in bullet list (row 3, column 2).</li> </ul></td> </tr>-<tr class="even">+<tr> <td></td> <td>Row 4; column 1 will be empty.</td> </tr>
test/command/1710.md view
@@ -57,7 +57,7 @@ \begin{frame}{Slide one} \phantomsection\label{slide-one} \begin{columns}[T]-\begin{column}{0.4\textwidth}+\begin{column}{0.4\linewidth} \begin{itemize} \tightlist \item@@ -67,7 +67,7 @@ \end{itemize} \end{column} -\begin{column}{0.4\textwidth}+\begin{column}{0.4\linewidth} \begin{itemize} \tightlist \item@@ -77,7 +77,7 @@ \end{itemize} \end{column} -\begin{column}{0.1\textwidth}+\begin{column}{0.1\linewidth} ok \end{column} \end{columns}
test/command/1881.md view
@@ -3,7 +3,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>@@ -11,7 +11,7 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td>@@ -44,7 +44,7 @@     (TableHead        ( "" , [] , [] )        [ Row-           ( "" , [ "header" ] , [] )+           ( "" , [] , [] )            [ Cell                ( "" , [] , [] )                AlignRight@@ -76,7 +76,7 @@         (RowHeadColumns 0)         []         [ Row-            ( "" , [ "odd" ] , [] )+            ( "" , [] , [] )             [ Cell                 ( "" , [] , [] )                 AlignRight@@ -111,7 +111,7 @@ ``` % pandoc -f html -t native <table>-<tr class="odd">+<tr> <td style="text-align: right;">12</td> <td style="text-align:left;">12</td> <td style="text-align:  center">12</td>@@ -133,7 +133,7 @@         (RowHeadColumns 0)         []         [ Row-            ( "" , [ "odd" ] , [] )+            ( "" , [] , [] )             [ Cell                 ( "" , [] , [] )                 AlignRight
test/command/2606.md view
@@ -6,7 +6,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td><p>* hello</p></td> </tr> </tbody>@@ -22,7 +22,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td><ul> <li>hello</li> </ul></td>@@ -40,7 +40,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td><p><code>* hello</code></p></td> </tr> </tbody>
test/command/2649.md view
@@ -7,7 +7,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> </tr> </tbody> </table>@@ -31,24 +31,24 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td><p>peildatum Simbase</p></td> <td><p>november 2005</p></td> <td colspan="2"><p><strong>uitslagen Flohrgambiet</strong></p></td> </tr>-<tr class="even">+<tr> <td><p>totaal aantal partijen Simbase</p></td> <td><p>7.316.773</p></td> <td><p>wit wint</p></td> <td><p>53%</p></td> </tr>-<tr class="odd">+<tr> <td><p>percentage (en partijen) Flohrgambiet</p></td> <td><p>0.023 % (1.699)</p></td> <td><p>zwart wint</p></td> <td><p>27%</p></td> </tr>-<tr class="even">+<tr> <td><p>percentage Flohrgambiet in aug 2003</p></td> <td><p>0.035 %</p></td> <td><p>remise</p></td>@@ -80,26 +80,26 @@ ^D <table> <thead>-<tr class="header">+<tr> <th><p>Plaats</p></th> <th><p>Rijder</p></th> <th><p>Aantal</p></th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td><p>1</p></td> <td style="text-align: left;"><p><a href="Sébastien_Loeb" title="wikilink">Sébastien Loeb</a></p></td> <td><p>78</p></td> </tr>-<tr class="even">+<tr> <td><p>2</p></td> <td style="text-align: left;"><p><strong><a href="Sébastien_Ogier" title="wikilink">Sébastien Ogier</a></strong></p></td> <td><p>38</p></td> </tr>-<tr class="odd">+<tr> <td><p>10</p></td> <td style="text-align: left;"><p><a href="Hannu_Mikkola" title="wikilink">Hannu Mikkola</a></p></td>
test/command/3314.md view
@@ -18,12 +18,12 @@ <col style="width: 15%" /> </colgroup> <tbody>-<tr class="odd">+<tr> <td>First</td> <td>12.0</td> <td>Example row spanning lines</td> </tr>-<tr class="even">+<tr> <td>Second</td> <td>5.0</td> <td>Another</td>
test/command/3432.md view
@@ -28,24 +28,24 @@ <col style="width: 54%" /> </colgroup> <thead>-<tr class="header">+<tr> <th>Treat</th> <th>Quantity</th> <th>Description</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Albatross</td> <td>2.99</td> <td>On a stick!</td> </tr>-<tr class="even">+<tr> <td>Crunchy Frog</td> <td>1.49</td> <td>If we took the bones out, it wouldn't be crunchy, now would it?</td> </tr>-<tr class="odd">+<tr> <td>Gannet Ripple</td> <td>1.99</td> <td>On a stick!</td>@@ -79,24 +79,24 @@ <table> <caption>Frozen Delights!</caption> <thead>-<tr class="header">+<tr> <th>Treat</th> <th>Quantity</th> <th>Description</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Albatross</td> <td>2.99</td> <td>On a stick!</td> </tr>-<tr class="even">+<tr> <td>Crunchy Frog</td> <td>1.49</td> <td>If we took the bones out, it wouldn't be crunchy, now would it?</td> </tr>-<tr class="odd">+<tr> <td>Gannet Ripple</td> <td>1.99</td> <td>On a stick!</td>@@ -130,24 +130,24 @@ <table> <caption>Frozen Delights!</caption> <thead>-<tr class="header">+<tr> <th>Treat</th> <th>Quantity</th> <th>Description</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Albatross</td> <td>2.99</td> <td>On a stick!</td> </tr>-<tr class="even">+<tr> <td>Crunchy Frog</td> <td>1.49</td> <td>If we took the bones out, it wouldn't be crunchy, now would it?</td> </tr>-<tr class="odd">+<tr> <td>Gannet Ripple</td> <td>1.99</td> <td>On a stick!</td>@@ -176,17 +176,17 @@ <table> <caption>Frozen Delights!</caption> <tbody>-<tr class="odd">+<tr> <td>Albatross</td> <td>2.99</td> <td>On a stick!</td> </tr>-<tr class="even">+<tr> <td>Crunchy Frog</td> <td>1.49</td> <td>If we took the bones out, it wouldn't be crunchy, now would it?</td> </tr>-<tr class="odd">+<tr> <td>Gannet Ripple</td> <td>1.99</td> <td>On a stick!</td>@@ -219,24 +219,24 @@ <table> <caption>Frozen Delights!</caption> <thead>-<tr class="header">+<tr> <th>Treat</th> <th>Quantity</th> <th>Description</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Albatross</td> <td>2.99</td> <td></td> </tr>-<tr class="even">+<tr> <td>Crunchy Frog</td> <td></td> <td>If we took the bones out, it wouldn't be crunchy, now would it?</td> </tr>-<tr class="odd">+<tr> <td>Gannet Ripple</td> <td>1.99</td> <td>On a stick!</td>@@ -266,7 +266,7 @@ <table> <caption>Frozen Delights!</caption> <tbody>-<tr class="odd">+<tr> <td>Albatross</td> <td>2.99</td> <td><ul>@@ -274,12 +274,12 @@ <li>In a cup!</li> </ul></td> </tr>-<tr class="even">+<tr> <td>Crunchy Frog</td> <td>1.49</td> <td>If we took the bones out, it wouldn't be crunchy, now would it?</td> </tr>-<tr class="odd">+<tr> <td>Gannet Ripple</td> <td>1.99</td> <td>On a stick!</td>
test/command/3450.md view
@@ -8,5 +8,5 @@ % pandoc -fmarkdown-implicit_figures -t latex ![image](lalune.jpg){height=2em} ^D-\includegraphics[width=\textwidth,height=2em]{lalune.jpg}+\includegraphics[width=\linewidth,height=2em,keepaspectratio]{lalune.jpg} ```
test/command/3494.md view
@@ -14,22 +14,22 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td style="text-align: right;"><span><strong>ﺍ</strong></span></td> <td style="text-align: left;"></td> <td style="text-align: left;"></td> </tr>-<tr class="even">+<tr> <td style="text-align: right;"><strong>ﺄﺤﺴﻨﺘـ(ﻭﺍ) IV</strong></td> <td style="text-align: left;"><em><span>ʾaḥsant(ū)</span></em></td> <td style="text-align: left;">thank you</td> </tr>-<tr class="odd">+<tr> <td style="text-align: right;"><em>blah</em></td> <td style="text-align: left;"><em>blah</em></td> <td style="text-align: left;"><em>blah</em></td> </tr>-<tr class="even">+<tr> <td style="text-align: right;">blah</td> <td style="text-align: left;">blah</td> <td style="text-align: left;">blah</td>
test/command/3499.md view
@@ -9,7 +9,7 @@ <li>|something|</li> <li><table> <tbody>-<tr class="odd">+<tr> <td>else</td> </tr> </tbody>
test/command/3667.md view
@@ -4,7 +4,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td><a href="http://example.com/">link text</a></td> </tr> </tbody>
test/command/4016.md view
@@ -16,7 +16,7 @@ \begin{frame}{Level 2 blocks} \phantomsection\label{level-2-blocks} \begin{columns}[T]-\begin{column}{0.4\textwidth}+\begin{column}{0.4\linewidth} \begin{block}{Block one} \phantomsection\label{block-one} \begin{itemize}@@ -27,7 +27,7 @@ \end{block} \end{column} -\begin{column}{0.6\textwidth}+\begin{column}{0.6\linewidth} \begin{block}{Block two} \phantomsection\label{block-two} \begin{itemize}
test/command/4690.md view
@@ -14,11 +14,11 @@ \begin{frame}{title} \phantomsection\label{title} \begin{columns}[T]-\begin{column}{0.08\textwidth}+\begin{column}{0.08\linewidth} content \end{column} -\begin{column}{0.84\textwidth}+\begin{column}{0.84\linewidth} content2 \end{column} \end{columns}
test/command/4742.md view
@@ -7,7 +7,7 @@ ^D [ Header     1-    ( "non-ascii--raksmorgas" , [] , [] )+    ( "non-ascii-warning-raksmorgas" , [] , [] )     [ Str "non"     , Space     , Str "ascii"@@ -29,7 +29,7 @@ ^D [ Header     1-    ( "non-ascii-\65039-r\228ksm\246rg\229s" , [] , [] )+    ( "non-ascii-warning-r\228ksm\246rg\229s" , [] , [] )     [ Str "non"     , Space     , Str "ascii"@@ -49,7 +49,7 @@ ^D [ Header     1-    ( "non-ascii-\65039-r\228ksm\246rg\229s" , [] , [] )+    ( "non-ascii-warning-r\228ksm\246rg\229s" , [] , [] )     [ Str "non"     , Space     , Str "ascii"
test/command/4805-beamer-columns-alignment.md view
@@ -19,18 +19,18 @@ ^D \begin{frame} \begin{columns}[T]-\begin{column}[c]{0.48\textwidth}+\begin{column}[c]{0.48\linewidth} \end{column} -\begin{column}[b]{0.48\textwidth}+\begin{column}[b]{0.48\linewidth} \end{column} \end{columns}  \begin{columns}[b,onlytextwidth]-\begin{column}[T]{0.48\textwidth}+\begin{column}[T]{0.48\linewidth} \end{column} -\begin{column}[t]{0.48\textwidth}+\begin{column}[t]{0.48\linewidth} \end{column} \end{columns} 
test/command/5367.md view
@@ -21,7 +21,7 @@ hello\footnote{doc footnote}  \begin{longtable}[]{@{}-  >{\centering\arraybackslash}p{(\columnwidth - 0\tabcolsep) * \real{0.1667}}@{}}+  >{\centering\arraybackslash}p{(\linewidth - 0\tabcolsep) * \real{0.1667}}@{}} \caption[Sample table.]{Sample table.\footnote{caption footnote}}\tabularnewline \toprule\noalign{} \begin{minipage}[b]{\linewidth}\centering
test/command/5476.md view
@@ -4,7 +4,7 @@ ^D \begin{figure} \centering-\includegraphics{test/lalune.jpg}+\pandocbounded{\includegraphics[keepaspectratio]{test/lalune.jpg}} \caption[moon]{moon\footnotemark{}} \end{figure} \footnotetext{the moon}
test/command/6033.md view
@@ -38,7 +38,7 @@  \begin{frame}{One-A} \begin{columns}[T]-\begin{column}{0.48\textwidth}+\begin{column}{0.48\linewidth} \begin{itemize} \tightlist \item@@ -46,7 +46,7 @@ \end{itemize} \end{column} -\begin{column}{0.48\textwidth}+\begin{column}{0.48\linewidth} \begin{itemize} \tightlist \item
+ test/command/6285.md view
@@ -0,0 +1,6 @@+```+% pandoc -t docx -f native -o - | pandoc -f docx -t native+[ HorizontalRule ]+^D+[ HorizontalRule ]+```
test/command/6441.md view
@@ -7,13 +7,13 @@ ^D <table class="table-dark"> <thead>-<tr class="header">+<tr> <th>h1</th> <th>h2</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>c1</td> <td>c2</td> </tr>
test/command/6481.md view
@@ -18,7 +18,7 @@ <col style="width: 69%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: center;">Col 1</th> <th style="text-align: center;">Col 2</th> <th style="text-align: center;">Col 3</th>@@ -26,7 +26,7 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: center;">High</td> <td style="text-align: center;">Med</td> <td style="text-align: center;">Med</td>
test/command/6549.md view
@@ -8,13 +8,13 @@ <table> <caption>Test table</caption> <thead>-<tr class="header">+<tr> <th>Column1</th> <th>Column2</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Data1</td> <td><ul> <li>data1</li>
test/command/7064.md view
@@ -15,14 +15,14 @@ <col style="width: 70%" /> </colgroup> <thead>-<tr class="header">+<tr> <th>Version</th> <th>Date</th> <th>Description</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>0.1.0</td> <td>18/02/2013</td> <td>Initial Release</td>
test/command/7112.md view
@@ -6,7 +6,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td>setting</td> <td><code>echo PATH="path"</code></td> </tr>
test/command/7181.md view
@@ -4,7 +4,7 @@ ^D \begin{figure} \centering-\includegraphics[page=13,trim=1cm,clip,width=4cm]{slides.pdf}+\pandocbounded{\includegraphics[keepaspectratio,page=13,trim=1cm,clip,width=4cm]{slides.pdf}} \caption{Global frog population.} \end{figure} 
test/command/7214.md view
@@ -13,12 +13,12 @@ <col style="width: 26%" /> </colgroup> <tbody>-<tr class="odd">+<tr> <td>日本語</td> <td>の文字列</td> <td>words in english</td> </tr>-<tr class="even">+<tr> <td>abc defghij</td> <td>def</td> <td>xyz</td>
+ test/command/7219.md view
@@ -0,0 +1,25 @@+```+% pandoc --citeproc -t plain+---+references:+- author:+  - family: Reese+    given: Trevor R.+  collection-title: 3rd series+  container-title: William and Mary Quarterly+  id: reese+  issued: 1958+  language: en-US+  page: 168-190+  title: Georgia in Anglo-Spanish diplomacy, 1736-1739+  type: article-journal+  volume: 15+...+and also in -@reese+^D+and also in (1958)++Reese, Trevor R. 1958. “Georgia in Anglo-Spanish Diplomacy, 1736-1739.”+William and Mary Quarterly, 3rd series, 15: 168–90.++```
test/command/7272.md view
@@ -15,7 +15,7 @@ </table> ^D \begin{longtable}[]{@{}-  >{\raggedright\arraybackslash}p{(\columnwidth - 0\tabcolsep) * \real{1.0000}}@{}}+  >{\raggedright\arraybackslash}p{(\linewidth - 0\tabcolsep) * \real{1.0000}}@{}} \toprule\noalign{} \endhead \bottomrule\noalign{}
test/command/7713.md view
@@ -11,14 +11,14 @@ <col style="width: 33%" /> </colgroup> <thead>-<tr class="header">+<tr> <th>aaaaaaaaaaaa</th> <th>bbbbb</th> <th>ccccccccccc</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td></td> <td></td> <td>cccccccccc cccccccccc cccccccccc cccccccccc cccccccccc
test/command/7847.md view
@@ -7,14 +7,14 @@ <col style="width: 20%" /> </colgroup> <thead>-<tr class="header">+<tr> <th>aaa</th> <th>bbb</th> <th>ccc</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Consequat nisi sit amet nibh. Nunc mi tortor, tristique sit amet, rhoncus porta, malesuada elementum, nisi.</td> <td></td>@@ -60,14 +60,14 @@ <col style="width: 20%" /> </colgroup> <thead>-<tr class="header">+<tr> <th>aaa</th> <th>bbb</th> <th>ccc</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Consequat nisi sit amet nibh. Nunc mi tortor, tristique sit amet, rhoncus porta, malesuada elementum, nisi.</td> <td>bbb</td>
test/command/7871.md view
@@ -6,7 +6,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td style="text-align: right; padding-right: 4px;">a</td> </tr> </tbody>
test/command/7919.md view
@@ -7,15 +7,15 @@ ^D <table> <thead>-<tr class="header">+<tr> <th>single column table</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>item 1</td> </tr>-<tr class="even">+<tr> <td>item 2</td> </tr> </tbody>@@ -31,15 +31,15 @@ ^D <table> <thead>-<tr class="header">+<tr> <th>single column table</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>item 1</td> </tr>-<tr class="even">+<tr> <td>item 2</td> </tr> </tbody>@@ -66,15 +66,15 @@ ^D <table> <thead>-<tr class="header">+<tr> <th>single column table</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>item 1</td> </tr>-<tr class="even">+<tr> <td>item 2</td> </tr> </tbody>@@ -90,15 +90,15 @@ ^D <table> <thead>-<tr class="header">+<tr> <th>single column table</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>item 1</td> </tr>-<tr class="even">+<tr> <td>item 2</td> </tr> </tbody>
test/command/8110.md view
@@ -18,19 +18,19 @@ ^D <table> <thead>-<tr class="header">+<tr> <th><p>Header text</p></th> <th><p>Header text</p></th> <th><p>Header text</p></th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td><p>Example</p></td> <td><p>Example</p></td> <td><p>Example</p></td> </tr>-<tr class="even">+<tr> <td><p>Example</p></td> <td><p>Example</p></td> <td><p>Example</p></td>
test/command/8216.md view
@@ -18,15 +18,15 @@ <col style="width: 44%" /> </colgroup> <tbody>-<tr class="odd">+<tr> <td>Some text</td> <td><span class="class1 class2 class3">text</span></td> </tr>-<tr class="even">+<tr> <td>Some text</td> <td><span class="class1 class2 class3">text</span></td> </tr>-<tr class="odd">+<tr> <td>Some text</td> <td><span class="class1 class2 class3">text</span></td> </tr>
test/command/8257.md view
@@ -16,22 +16,22 @@ <col style="width: 11%" /> </colgroup> <thead>-<tr class="header">+<tr> <th>Item</th> <th>Price</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Eggs</td> <td>5£</td> </tr>-<tr class="even">+<tr> <td>Spam</td> <td>3£</td> </tr> </tbody><tfoot>-<tr class="odd">+<tr> <td>Sum</td> <td>8£</td> </tr>
test/command/8307.md view
@@ -13,7 +13,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td title="this   &#10; breaks">hello</td>
test/command/8659.md view
@@ -5,7 +5,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> </tr> </tbody> </table>@@ -30,20 +30,20 @@ <col style="width: 16%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: left;"></th> <th></th> <th style="text-align: right;"></th> <th style="text-align: right;"><table> <tbody>-<tr class="odd">+<tr> </tr> </tbody> </table></th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: left;">a</td> <td>b</td> <td style="text-align: right;">c</td>
test/command/8770-block.md view
@@ -39,13 +39,13 @@ <col style="width: 16%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: center;">Fruit<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a></th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: center;">Bans<a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a></td> </tr>
test/command/8770-document.md view
@@ -32,13 +32,13 @@ <col style="width: 16%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: center;">Fruit<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a></th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: center;">Bans<a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a></td> </tr>
test/command/8770-section.md view
@@ -32,13 +32,13 @@ <col style="width: 16%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: center;">Fruit<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a></th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: center;">Bans<a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a></td> </tr>
test/command/8789.md view
@@ -16,7 +16,7 @@ ^D <table> <thead>-<tr class="header">+<tr> <th style="text-align: right;"><strong>First</strong></th> <th style="text-align: right;"><strong>Second</strong></th> <th style="text-align: left;"><strong>Third</strong></th>@@ -24,13 +24,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: right;">160</td> <td style="text-align: right;">1</td> <td style="text-align: left;">test</td> <td style="text-align: left;">test</td> </tr>-<tr class="even">+<tr> <td style="text-align: right;">160</td> <td style="text-align: right;">2</td> <td colspan="2" style="text-align: left;"><em>This is a test:</em> <span
test/command/8948.md view
@@ -1,19 +1,31 @@ ``` % pandoc --embed-resources-![minimal](command/minimal.svg)-![minimal](command/minimal.svg)+![minimal](command/minimal.svg){.inline-svg}+![minimal](command/minimal.svg){.inline-svg} ^D-<p><svg role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150"><use href="#svg_7868854ffb8f30209cd0" width="100%" height="100%" /></svg> <svg id="svg_7868854ffb8f30209cd0" role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150">+<p><svg role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150"><use href="#svg_7868854ffb8f30209cd0" width="100%" height="100%" /></svg>+<svg id="svg_7868854ffb8f30209cd0" role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150">     <path d="M 0 35.5 L 6.5 22.5 L 16 37 L 23 24 L 34.8 43.7 L 42.5 30 L 50.3 47 L 59.7 27.7 L 69 47 L 85 17.7 L 98.3 39 L 113 9.7 L 127.7 42.3 L 136.3 23.7 L 147 44.3 L 158.3 20.3 L 170.3 40.3 L 177.7 25.7 L 189.7 43 L 199.7 21 L 207.7 35 L 219 11 L 233 37 L 240.3 23.7 L 251 43 L 263 18.3 L 272.7 33.3 L 283 10 L 295 32.3 L 301.3 23 L 311.7 37 L 323.7 7.7 L 339.3 39 L 346.3 25.7 L 356.3 42.3 L 369.7 15 L 376.3 25.7 L 384 9 L 393 28.3 L 400.3 19 L 411.7 38.3 L 421 21 L 434.3 43 L 445 25 L 453 36.3 L 464.3 18.3 L 476.2 40.3 L 480 33.5 L 480 215 L 0 215 L 0 35.5 Z" fill="#175720" /> </svg></p> ```  ``` % pandoc --embed-resources-![minimal](command/minimal.svg)-![minimal](command/minimal.svg){#foo}+![minimal](command/minimal.svg){.inline-svg}+![minimal](command/minimal.svg){#foo .inline-svg} ^D-<p><svg role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150"><use href="#foo" width="100%" height="100%" /></svg> <svg id="foo" role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150">+<p><svg role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150"><use href="#foo" width="100%" height="100%" /></svg>+<svg id="foo" role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150">     <path d="M 0 35.5 L 6.5 22.5 L 16 37 L 23 24 L 34.8 43.7 L 42.5 30 L 50.3 47 L 59.7 27.7 L 69 47 L 85 17.7 L 98.3 39 L 113 9.7 L 127.7 42.3 L 136.3 23.7 L 147 44.3 L 158.3 20.3 L 170.3 40.3 L 177.7 25.7 L 189.7 43 L 199.7 21 L 207.7 35 L 219 11 L 233 37 L 240.3 23.7 L 251 43 L 263 18.3 L 272.7 33.3 L 283 10 L 295 32.3 L 301.3 23 L 311.7 37 L 323.7 7.7 L 339.3 39 L 346.3 25.7 L 356.3 42.3 L 369.7 15 L 376.3 25.7 L 384 9 L 393 28.3 L 400.3 19 L 411.7 38.3 L 421 21 L 434.3 43 L 445 25 L 453 36.3 L 464.3 18.3 L 476.2 40.3 L 480 33.5 L 480 215 L 0 215 L 0 35.5 Z" fill="#175720" /> </svg></p>+```++```+% pandoc --embed-resources+![minimal](command/minimal.svg)+^D+<figure>+<img role="img" aria-label="minimal" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PgoKPHN2ZyB2aWV3Qm94PSItLjMzMyAtLjMzMyA0ODAgMTUwIiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjojZmZmZmZmMDAiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CiAgICA8cGF0aCBkPSJNIDAgMzUuNSBMIDYuNSAyMi41IEwgMTYgMzcgTCAyMyAyNCBMIDM0LjggNDMuNyBMIDQyLjUgMzAgTCA1MC4zIDQ3IEwgNTkuNyAyNy43IEwgNjkgNDcgTCA4NSAxNy43IEwgOTguMyAzOSBMIDExMyA5LjcgTCAxMjcuNyA0Mi4zIEwgMTM2LjMgMjMuNyBMIDE0NyA0NC4zIEwgMTU4LjMgMjAuMyBMIDE3MC4zIDQwLjMgTCAxNzcuNyAyNS43IEwgMTg5LjcgNDMgTCAxOTkuNyAyMSBMIDIwNy43IDM1IEwgMjE5IDExIEwgMjMzIDM3IEwgMjQwLjMgMjMuNyBMIDI1MSA0MyBMIDI2MyAxOC4zIEwgMjcyLjcgMzMuMyBMIDI4MyAxMCBMIDI5NSAzMi4zIEwgMzAxLjMgMjMgTCAzMTEuNyAzNyBMIDMyMy43IDcuNyBMIDMzOS4zIDM5IEwgMzQ2LjMgMjUuNyBMIDM1Ni4zIDQyLjMgTCAzNjkuNyAxNSBMIDM3Ni4zIDI1LjcgTCAzODQgOSBMIDM5MyAyOC4zIEwgNDAwLjMgMTkgTCA0MTEuNyAzOC4zIEwgNDIxIDIxIEwgNDM0LjMgNDMgTCA0NDUgMjUgTCA0NTMgMzYuMyBMIDQ2NC4zIDE4LjMgTCA0NzYuMiA0MC4zIEwgNDgwIDMzLjUgTCA0ODAgMjE1IEwgMCAyMTUgTCAwIDM1LjUgWiIgZmlsbD0iIzE3NTcyMCIvPgo8L3N2Zz4K" alt="minimal" />+<figcaption aria-hidden="true">minimal</figcaption>+</figure> ```
test/command/9002.md view
@@ -8,7 +8,7 @@ <col style="width: 50%" /> </colgroup> <thead>-<tr class="header">+<tr> <th>a</th> <th>b</th> </tr>
test/command/9045.md view
@@ -4,7 +4,7 @@ ^D \begin{figure} \centering-\includegraphics{there.jpg}+\pandocbounded{\includegraphics[keepaspectratio]{there.jpg}} \caption{hi}\label{foo} \end{figure} ```
+ test/command/9358.docx view

binary file changed (absent → 13439 bytes)

+ test/command/9358.md view
@@ -0,0 +1,45 @@+Caption belongs to the second table:+```+% pandoc -f docx -t html command/9358.docx+^D+<p>Lorem gipsum</p>+<table>+<colgroup>+<col style="width: 50%" />+<col style="width: 50%" />+</colgroup>+<thead>+<tr>+<th>A</th>+<th>B</th>+</tr>+</thead>+<tbody>+<tr>+<td>C</td>+<td>D</td>+</tr>+</tbody>+</table>+<p>Lorem ipsum</p>+<table>+<caption><p>Table 1 Numbers from 1 to 4</p></caption>+<colgroup>+<col style="width: 50%" />+<col style="width: 50%" />+</colgroup>+<thead>+<tr>+<th>1</th>+<th>2</th>+</tr>+</thead>+<tbody>+<tr>+<td>3</td>+<td>4</td>+</tr>+</tbody>+</table>+<p>Lorem yipsum</p>+```
+ test/command/9391.docx view

binary file changed (absent → 13701 bytes)

+ test/command/9391.md view
@@ -0,0 +1,9 @@+```+% pandoc command/9391.docx -t html+^D+<p>Lorem ipsum.</p>+<figure>+<img src="media/image1.png" style="width:1.10263in;height:1.10263in" />+<figcaption><p>Blue square.</p></figcaption>+</figure>+```
test/command/9420.md view
@@ -1,6 +1,6 @@ ``` % pandoc --embed-resources-![](command/9420.svg)+![](command/9420.svg){.inline-svg} ^D <p><svg id="svg_e1815ef374a63cf552e4" role="img" width="504pt" height="360pt" viewBox="0 0 504 360"> <defs>
test/command/9467.md view
@@ -2,57 +2,6 @@ % pandoc --embed-resources ![](command/9467.svg) ^D-<p><svg id="svg2" role="img" width="191.56267" height="151.71201" viewBox="0 0 191.56267 151.71201" xmlns:svg="http://www.w3.org/2000/svg">-  <defs id="svg2_defs6">-    <clipPath clipPathUnits="userSpaceOnUse" id="svg2_clipPath24">-      <path d="M 56.69362,0 113.38724,113.38724 170.08086,0 Z" id="svg2_path22" />-    </clipPath>-    <clipPath clipPathUnits="userSpaceOnUse" id="svg2_clipPath38">-      <path d="M 0,0 H 100 V 100 H 0 Z" id="svg2_path36" />-    </clipPath>-    <radialGradient fx="50.000641" fy="50.000641" cx="50.000641" cy="50.000641" r="50.000641" gradientUnits="userSpaceOnUse" id="svg2_radialGradient46">-      <stop style="stop-opacity:1;stop-color:#ffffff" offset="0" id="svg2_stop40"></stop>-      <stop style="stop-opacity:1;stop-color:#9999ff" offset="25.00032" id="svg2_stop42"></stop>-      <stop style="stop-opacity:1;stop-color:#9999ff" offset="50.00064" id="svg2_stop44"></stop>-    </radialGradient>-  </defs>-  <g id="svg2_g8" transform="matrix(1.3333333,0,0,-1.3333333,0,151.712)">-    <g id="svg2_g10" transform="translate(-26.606,0.199)">-      <g id="svg2_g12">-        <g id="svg2_g14">-          <g id="svg2_g16">-            <g id="svg2_g18">-              <g id="svg2_g20" clip-path="url(#svg2_clipPath24)">-                <g id="svg2_g26" transform="matrix(2.26802,0,0,2.26802,113.38724,56.69362)">-                  <g id="svg2_g28">-                    <g id="svg2_g30" transform="translate(-50,-50)">-                      <g id="svg2_g32">-                        <g id="svg2_g34" clip-path="url(#svg2_clipPath38)">-                          <path d="M 0,0 H 100 V 100 H 0 Z" style="fill:url(#svg2_radialGradient46);stroke:none" id="svg2_path48" />-                        </g>-                      </g>-                    </g>-                  </g>-                </g>-              </g>-            </g>-            <path d="M 56.69362,0 113.38724,113.38724 170.08086,0 Z" style="fill:none;stroke:#9999ff;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1" id="svg2_path50" />-            <g id="svg2_g52">-              <g id="svg2_g54" transform="translate(63.337,5.457)">-                <g id="svg2_g56">-                  <g id="svg2_g58" transform="translate(-36.731,-5.656)">-                    <text xml:space="preserve" transform="matrix(1,0,0,-1,36.731,5.656)" style="font-variant:normal;font-weight:normal;font-size:9.9626px;font-family:CMSS10;-inkscape-font-specification:CMSS10;writing-mode:lr-tb;fill:#9999ff;fill-opacity:1;fill-rule:nonzero;stroke:none" id="svg2_text62"><tspan x="0 4.9812999 8.38552 13.173546 18.321222 20.701286 25.128666 30.27634 37.191383 41.010048 46.157722 50.945747 56.093422 60.520802 68.995987 72.593483 75.997704 78.377769 83.165794 88.303505 93.284805 95.664871" y="0" id="svg2_tspan60">gradientshadedtriangle</tspan></text>-                    <g id="svg2_g64" transform="translate(36.731,5.656)"></g>-                  </g>-                </g>-                <g id="svg2_g66" transform="translate(-63.337,-5.457)"></g>-              </g>-            </g>-          </g>-        </g>-      </g>-    </g>-  </g>-</svg></p>+<p><img role="img" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTkiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB2ZXJzaW9uPSIxLjEiIGlkPSJzdmcyIiB3aWR0aD0iMTkxLjU2MjY3IiBoZWlnaHQ9IjE1MS43MTIwMSIgdmlld0JveD0iMCAwIDE5MS41NjI2NyAxNTEuNzEyMDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPGRlZnMgaWQ9ImRlZnM2Ij4KICAgIDxjbGlwUGF0aCBjbGlwUGF0aFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgaWQ9ImNsaXBQYXRoMjQiPgogICAgICA8cGF0aCBkPSJNIDU2LjY5MzYyLDAgMTEzLjM4NzI0LDExMy4zODcyNCAxNzAuMDgwODYsMCBaIiBpZD0icGF0aDIyIiAvPgogICAgPC9jbGlwUGF0aD4KICAgIDxjbGlwUGF0aCBjbGlwUGF0aFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgaWQ9ImNsaXBQYXRoMzgiPgogICAgICA8cGF0aCBkPSJNIDAsMCBIIDEwMCBWIDEwMCBIIDAgWiIgaWQ9InBhdGgzNiIgLz4KICAgIDwvY2xpcFBhdGg+CiAgICA8cmFkaWFsR3JhZGllbnQgZng9IjUwLjAwMDY0MSIgZnk9IjUwLjAwMDY0MSIgY3g9IjUwLjAwMDY0MSIgY3k9IjUwLjAwMDY0MSIgcj0iNTAuMDAwNjQxIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgaWQ9InJhZGlhbEdyYWRpZW50NDYiPgogICAgICA8c3RvcCBzdHlsZT0ic3RvcC1vcGFjaXR5OjE7c3RvcC1jb2xvcjojZmZmZmZmIiBvZmZzZXQ9IjAiIGlkPSJzdG9wNDAiIC8+CiAgICAgIDxzdG9wIHN0eWxlPSJzdG9wLW9wYWNpdHk6MTtzdG9wLWNvbG9yOiM5OTk5ZmYiIG9mZnNldD0iMjUuMDAwMzIiIGlkPSJzdG9wNDIiIC8+CiAgICAgIDxzdG9wIHN0eWxlPSJzdG9wLW9wYWNpdHk6MTtzdG9wLWNvbG9yOiM5OTk5ZmYiIG9mZnNldD0iNTAuMDAwNjQiIGlkPSJzdG9wNDQiIC8+CiAgICA8L3JhZGlhbEdyYWRpZW50PgogIDwvZGVmcz4KICA8ZyBpZD0iZzgiIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDE1MS43MTIpIj4KICAgIDxnIGlkPSJnMTAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yNi42MDYsMC4xOTkpIj4KICAgICAgPGcgaWQ9ImcxMiI+CiAgICAgICAgPGcgaWQ9ImcxNCI+CiAgICAgICAgICA8ZyBpZD0iZzE2Ij4KICAgICAgICAgICAgPGcgaWQ9ImcxOCI+CiAgICAgICAgICAgICAgPGcgaWQ9ImcyMCIgY2xpcC1wYXRoPSJ1cmwoI2NsaXBQYXRoMjQpIj4KICAgICAgICAgICAgICAgIDxnIGlkPSJnMjYiIHRyYW5zZm9ybT0ibWF0cml4KDIuMjY4MDIsMCwwLDIuMjY4MDIsMTEzLjM4NzI0LDU2LjY5MzYyKSI+CiAgICAgICAgICAgICAgICAgIDxnIGlkPSJnMjgiPgogICAgICAgICAgICAgICAgICAgIDxnIGlkPSJnMzAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC01MCwtNTApIj4KICAgICAgICAgICAgICAgICAgICAgIDxnIGlkPSJnMzIiPgogICAgICAgICAgICAgICAgICAgICAgICA8ZyBpZD0iZzM0IiBjbGlwLXBhdGg9InVybCgjY2xpcFBhdGgzOCkiPgogICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0gMCwwIEggMTAwIFYgMTAwIEggMCBaIiBzdHlsZT0iZmlsbDp1cmwoI3JhZGlhbEdyYWRpZW50NDYpO3N0cm9rZTpub25lIiBpZD0icGF0aDQ4IiAvPgogICAgICAgICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICA8L2c+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0gNTYuNjkzNjIsMCAxMTMuMzg3MjQsMTEzLjM4NzI0IDE3MC4wODA4NiwwIFoiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiM5OTk5ZmY7c3Ryb2tlLXdpZHRoOjAuMzk4NTtzdHJva2UtbGluZWNhcDpidXR0O3N0cm9rZS1saW5lam9pbjptaXRlcjtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2UtZGFzaGFycmF5Om5vbmU7c3Ryb2tlLW9wYWNpdHk6MSIgaWQ9InBhdGg1MCIgLz4KICAgICAgICAgICAgPGcgaWQ9Imc1MiI+CiAgICAgICAgICAgICAgPGcgaWQ9Imc1NCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNjMuMzM3LDUuNDU3KSI+CiAgICAgICAgICAgICAgICA8ZyBpZD0iZzU2Ij4KICAgICAgICAgICAgICAgICAgPGcgaWQ9Imc1OCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTM2LjczMSwtNS42NTYpIj4KICAgICAgICAgICAgICAgICAgICA8dGV4dCB4bWw6c3BhY2U9InByZXNlcnZlIiB0cmFuc2Zvcm09Im1hdHJpeCgxLDAsMCwtMSwzNi43MzEsNS42NTYpIiBzdHlsZT0iZm9udC12YXJpYW50Om5vcm1hbDtmb250LXdlaWdodDpub3JtYWw7Zm9udC1zaXplOjkuOTYyNnB4O2ZvbnQtZmFtaWx5OkNNU1MxMDstaW5rc2NhcGUtZm9udC1zcGVjaWZpY2F0aW9uOkNNU1MxMDt3cml0aW5nLW1vZGU6bHItdGI7ZmlsbDojOTk5OWZmO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiBpZD0idGV4dDYyIj48dHNwYW4geD0iMCA0Ljk4MTI5OTkgOC4zODU1MiAxMy4xNzM1NDYgMTguMzIxMjIyIDIwLjcwMTI4NiAyNS4xMjg2NjYgMzAuMjc2MzQgMzcuMTkxMzgzIDQxLjAxMDA0OCA0Ni4xNTc3MjIgNTAuOTQ1NzQ3IDU2LjA5MzQyMiA2MC41MjA4MDIgNjguOTk1OTg3IDcyLjU5MzQ4MyA3NS45OTc3MDQgNzguMzc3NzY5IDgzLjE2NTc5NCA4OC4zMDM1MDUgOTMuMjg0ODA1IDk1LjY2NDg3MSIgeT0iMCIgaWQ9InRzcGFuNjAiPmdyYWRpZW50c2hhZGVkdHJpYW5nbGU8L3RzcGFuPjwvdGV4dD4KICAgICAgICAgICAgICAgICAgICA8ZyBpZD0iZzY0IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzNi43MzEsNS42NTYpIiAvPgogICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8ZyBpZD0iZzY2IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNjMuMzM3LC01LjQ1NykiIC8+CiAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICA8L2c+CiAgICAgICAgICA8L2c+CiAgICAgICAgPC9nPgogICAgICA8L2c+CiAgICA8L2c+CiAgPC9nPgo8L3N2Zz4K" /></p>  ```
test/command/9472.md view
@@ -61,7 +61,7 @@ \let\LanguageShortHands\languageshorthands \def\languageshorthands#1{} \ifLuaTeX-  \usepackage{selnolig}  % disable illegal ligatures+  \usepackage[german]{selnolig} % disable illegal ligatures \fi \usepackage{bookmark} \IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available
test/command/9652.md view
@@ -1,9 +1,9 @@ ```` % pandoc -f markdown -t html --embed-resources ```{=html}-<img class="something" src="command/9652.svg" />+<img class="something inline-svg" src="command/9652.svg" /> ``` ^D-<svg id="svg_b627f92299158b36552b" role="img" width="504.00pt" height="360.00pt" viewBox="0 0 504.00 360.00" class="something please-do-not-delete-me">+<svg id="svg_b627f92299158b36552b" role="img" width="504.00pt" height="360.00pt" viewBox="0 0 504.00 360.00" class="something inline-svg please-do-not-delete-me"> </svg> ````
+ test/command/9777-b.md view
@@ -0,0 +1,62 @@+```+% pandoc -f native -t typst+[ Table+    ( "" , [] , [ ( "typst:figure:kind" , "figure" ) ] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "f" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "b" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]+^D+#figure(+  align(center)[#table(+    columns: 2,+    align: (auto,auto,),+    table.header([f], [b],),+    table.hline(),+    [1], [2],+  )]+  , kind: figure+  )+```+
+ test/command/9777.md view
@@ -0,0 +1,58 @@+```+% pandoc -f native -t typst+[ Table+    ( "" , [ "typst:no-figure" ] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault )+    , ( AlignDefault , ColWidthDefault )+    ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "f" ] ]+           , Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain [ Str "b" ] ]+           ]+       ])+    [ TableBody+        ( "" , [] , [] )+        (RowHeadColumns 0)+        []+        [ Row+            ( "" , [] , [] )+            [ Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "1" ] ]+            , Cell+                ( "" , [] , [] )+                AlignDefault+                (RowSpan 1)+                (ColSpan 1)+                [ Plain [ Str "2" ] ]+            ]+        ]+    ]+    (TableFoot ( "" , [] , [] ) [])+]+^D+#table(+  columns: 2,+  align: (auto,auto,),+  table.header([f], [b],),+  table.hline(),+  [1], [2],+)+```
+ test/command/9792.md view
@@ -0,0 +1,21 @@+```+% pandoc -t gfm+- list item+  <details>++  - subitem+  </details>++  item _continue_ **with** formatting+- next list item+^D+- list item+  <details>++  - subitem++  </details>++  item *continue* **with** formatting+- next list item+```
+ test/command/9797.md view
@@ -0,0 +1,39 @@+```+% pandoc -t native -f csv+"one_line_break:+four_line_breaks:++++last_line"+^D+[ Table+    ( "" , [] , [] )+    (Caption Nothing [])+    [ ( AlignDefault , ColWidthDefault ) ]+    (TableHead+       ( "" , [] , [] )+       [ Row+           ( "" , [] , [] )+           [ Cell+               ( "" , [] , [] )+               AlignDefault+               (RowSpan 1)+               (ColSpan 1)+               [ Plain+                   [ Str "one_line_break:"+                   , LineBreak+                   , Str "four_line_breaks:"+                   , LineBreak+                   , LineBreak+                   , LineBreak+                   , LineBreak+                   , Str "last_line"+                   ]+               ]+           ]+       ])+    [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+    (TableFoot ( "" , [] , [] ) [])+]+```
+ test/command/9805.md view
@@ -0,0 +1,10 @@+```+% pandoc -f rst -t native+word.*word+------------+* abc+^D+[ Header 1 ( "word.word" , [] , [] ) [ Str "word.*word" ]+, BulletList [ [ Plain [ Str "abc" ] ] ]+]+```
+ test/command/9807.md view
@@ -0,0 +1,13 @@+```+% pandoc -f typst -t native+#let foo = [+  bar baz+]+*#foo*+^D+[ Para+    [ Strong+        [ SoftBreak , Str "bar" , Space , Str "baz" , SoftBreak ]+    ]+]+```
+ test/command/9809.md view
@@ -0,0 +1,14 @@+```+% pandoc -f html -t native+<ul>+  <li>Bullet point.</li>+  <p>Nested line.</p>+</ul>+^D+[ BulletList+    [ [ Para [ Str "Bullet" , Space , Str "point." ]+      , Para [ Str "Nested" , Space , Str "line." ]+      ]+    ]+]+```
+ test/command/9878.md view
@@ -0,0 +1,6 @@+```+% pandoc -f textile -t native+15% 50%+^D+[ Para [ Str "15%" , Space , Str "50%" ] ]+```
+ test/command/9902.md view
@@ -0,0 +1,6 @@+```+% pandoc -t native -f latex+raw_tex+\kern.1pt+^D+[ RawBlock (Format "latex") "\\kern.1pt" ]+```
+ test/command/9904.md view
@@ -0,0 +1,182 @@+```+% pandoc -f rst -t native --citeproc --bibliography command/biblio.bib+The axioms were introduced by :cite:t:`{see}item1`.+The axioms were introduced by :cite:t:`item1{p. 1166}`.+The axioms were introduced by :cite:t:`{see}item1{p. 1166}`.+Axioms were introduced :cite:`{see}item1`.+Axioms were introduced :cite:p:`item1{p. 1166}`.+Axioms were introduced :cite:p:`{see}item1{p. 1166}`.++.. bibliography::+^D+[ Para+    [ Str "The"+    , Space+    , Str "axioms"+    , Space+    , Str "were"+    , Space+    , Str "introduced"+    , Space+    , Str "by"+    , Space+    , Cite+        [ Citation+            { citationId = "item1"+            , citationPrefix = [ Str "see" ]+            , citationSuffix = []+            , citationMode = AuthorInText+            , citationNoteNum = 0+            , citationHash = 0+            }+        ]+        [ Str "(see" , Space , Str "Doe;" , Space , Str "2005)" ]+    , Str "."+    , SoftBreak+    , Str "The"+    , Space+    , Str "axioms"+    , Space+    , Str "were"+    , Space+    , Str "introduced"+    , Space+    , Str "by"+    , Space+    , Cite+        [ Citation+            { citationId = "item1"+            , citationPrefix = []+            , citationSuffix = [ Str "p." , Space , Str "1166" ]+            , citationMode = AuthorInText+            , citationNoteNum = 0+            , citationHash = 0+            }+        ]+        [ Str "Doe" , Space , Str "(2005," , Space , Str "1166)" ]+    , Str "."+    , SoftBreak+    , Str "The"+    , Space+    , Str "axioms"+    , Space+    , Str "were"+    , Space+    , Str "introduced"+    , Space+    , Str "by"+    , Space+    , Cite+        [ Citation+            { citationId = "item1"+            , citationPrefix = [ Str "see" ]+            , citationSuffix = [ Str "p." , Space , Str "1166" ]+            , citationMode = AuthorInText+            , citationNoteNum = 0+            , citationHash = 0+            }+        ]+        [ Str "(see"+        , Space+        , Str "Doe;"+        , Space+        , Str "2005,"+        , Space+        , Str "1166)"+        ]+    , Str "."+    , SoftBreak+    , Str "Axioms"+    , Space+    , Str "were"+    , Space+    , Str "introduced"+    , Space+    , Cite+        [ Citation+            { citationId = "item1"+            , citationPrefix = [ Str "see" ]+            , citationSuffix = []+            , citationMode = NormalCitation+            , citationNoteNum = 0+            , citationHash = 0+            }+        ]+        [ Str "(see" , Space , Str "Doe" , Space , Str "2005)" ]+    , Str "."+    , SoftBreak+    , Str "Axioms"+    , Space+    , Str "were"+    , Space+    , Str "introduced"+    , Space+    , Cite+        [ Citation+            { citationId = "item1"+            , citationPrefix = []+            , citationSuffix = [ Str "p." , Space , Str "1166" ]+            , citationMode = NormalCitation+            , citationNoteNum = 0+            , citationHash = 0+            }+        ]+        [ Str "(Doe" , Space , Str "2005," , Space , Str "1166)" ]+    , Str "."+    , SoftBreak+    , Str "Axioms"+    , Space+    , Str "were"+    , Space+    , Str "introduced"+    , Space+    , Cite+        [ Citation+            { citationId = "item1"+            , citationPrefix = [ Str "see" ]+            , citationSuffix = [ Str "p." , Space , Str "1166" ]+            , citationMode = NormalCitation+            , citationNoteNum = 0+            , citationHash = 0+            }+        ]+        [ Str "(see"+        , Space+        , Str "Doe"+        , Space+        , Str "2005,"+        , Space+        , Str "1166)"+        ]+    , Str "."+    ]+, Div+    ( "refs"+    , [ "references" , "csl-bib-body" , "hanging-indent" ]+    , [ ( "entry-spacing" , "0" ) ]+    )+    [ Div+        ( "ref-item1" , [ "csl-entry" ] , [] )+        [ Para+            [ Str "Doe,"+            , Space+            , Str "John."+            , Space+            , Str "2005."+            , Space+            , Emph [ Str "First" , Space , Str "Book" ]+            , Str "."+            , Space+            , Str "Cambridge:"+            , Space+            , Str "Cambridge"+            , Space+            , Str "University"+            , Space+            , Str "Press."+            ]+        ]+    ]+]++```
+ test/command/9905.md view
@@ -0,0 +1,20 @@+```+% pandoc -t html5+# Section Ψ {#Ψ}++look at [Section Ψ](#Ψ).+^D+<h1 id="Ψ">Section Ψ</h1>+<p>look at <a href="#Ψ">Section Ψ</a>.</p>++```+```+% pandoc -t html4+# Section Ψ {#Ψ}++look at [Section Ψ](#Ψ).+^D+<h1 id="Ψ">Section Ψ</h1>+<p>look at <a href="#%CE%A8">Section Ψ</a>.</p>++```
+ test/command/9908.md view
@@ -0,0 +1,10 @@+```+% pandoc -f native -t markdown+[ BulletList+    [ [ BlockQuote [ Para [ Str "a" ] , Para [ Str "b" ] ] ] ]+]+^D+-   > a+    >+    > b+```
test/docx/custom-style-reference.docx view

binary file changed (14846 → 14838 bytes)

test/docx/deep_normalize.native view
@@ -1,6 +1,6 @@ [OrderedList (1,Decimal,OneParen)  [[Para [Str "This",Space,Str "is",Space,Str "at",Space,Str "the",Space,Str "first",Space,Str "level"]-  ,OrderedList (1,LowerAlpha,DefaultDelim)+  ,OrderedList (1,LowerAlpha,OneParen)    [[Para [Str "This",Space,Str "is",Space,Str "at",Space,Str "the",Space,Str "second",Space,Str "level"]-    ,OrderedList (1,LowerRoman,DefaultDelim)+    ,OrderedList (1,LowerRoman,OneParen)      [[Para [Str "This",Space,Str "is",Space,Emph [Str "at",Space,Strong [Str "the",Space,Span ("",["mark"],[]) [Str "th"],Str "i",Span ("",["mark"],[]) [Str "rd"],Space,Str "level"],Str ",",Space,Str "and",Space,Str "I",Space,Str "want",Space,Str "to"],Space,Str "test",Space,Str "normalization",Space,Str "here."]]]]]]]]
test/docx/golden/block_quotes.docx view

binary file changed (10651 → 10657 bytes)

test/docx/golden/codeblock.docx view

binary file changed (10466 → 10474 bytes)

test/docx/golden/comments.docx view

binary file changed (10799 → 10805 bytes)

test/docx/golden/custom_style_no_reference.docx view

binary file changed (10568 → 10577 bytes)

test/docx/golden/custom_style_preserve.docx view

binary file changed (11196 → 11204 bytes)

test/docx/golden/custom_style_reference.docx view

binary file changed (12519 → 12436 bytes)

test/docx/golden/definition_list.docx view

binary file changed (10465 → 10474 bytes)

test/docx/golden/document-properties-short-desc.docx view

binary file changed (10472 → 10481 bytes)

test/docx/golden/document-properties.docx view

binary file changed (10958 → 10967 bytes)

test/docx/golden/headers.docx view

binary file changed (10605 → 10614 bytes)

test/docx/golden/image.docx view

binary file changed (27347 → 27354 bytes)

test/docx/golden/inline_code.docx view

binary file changed (10405 → 10413 bytes)

test/docx/golden/inline_formatting.docx view

binary file changed (10586 → 10592 bytes)

test/docx/golden/inline_images.docx view

binary file changed (27345 → 27350 bytes)

binary file changed (10627 → 10635 bytes)

test/docx/golden/links.docx view

binary file changed (10798 → 10804 bytes)

test/docx/golden/lists.docx view

binary file changed (10997 → 11005 bytes)

test/docx/golden/lists_continuing.docx view

binary file changed (10661 → 10667 bytes)

test/docx/golden/lists_div_bullets.docx view

binary file changed (10645 → 10651 bytes)

test/docx/golden/lists_multiple_initial.docx view

binary file changed (10879 → 10885 bytes)

test/docx/golden/lists_restarting.docx view

binary file changed (10659 → 10665 bytes)

test/docx/golden/nested_anchors_in_header.docx view

binary file changed (10798 → 10806 bytes)

test/docx/golden/notes.docx view

binary file changed (10574 → 10583 bytes)

test/docx/golden/raw-blocks.docx view

binary file changed (10506 → 10512 bytes)

test/docx/golden/raw-bookmarks.docx view

binary file changed (10640 → 10646 bytes)

test/docx/golden/table_one_row.docx view

binary file changed (10489 → 10487 bytes)

test/docx/golden/table_with_list_cell.docx view

binary file changed (10938 → 10939 bytes)

test/docx/golden/tables-default-widths.docx view

binary file changed (10834 → 10850 bytes)

test/docx/golden/tables.docx view

binary file changed (10848 → 10863 bytes)

test/docx/golden/tables_separated_with_rawblock.docx view

binary file changed (10487 → 10485 bytes)

+ test/docx/golden/task_list.docx view

binary file changed (absent → 10750 bytes)

test/docx/golden/track_changes_deletion.docx view

binary file changed (10449 → 10457 bytes)

test/docx/golden/track_changes_insertion.docx view

binary file changed (10432 → 10439 bytes)

test/docx/golden/track_changes_move.docx view

binary file changed (10466 → 10470 bytes)

test/docx/golden/track_changes_scrubbed_metadata.docx view

binary file changed (10575 → 10584 bytes)

test/docx/golden/unicode.docx view

binary file changed (10391 → 10431 bytes)

test/docx/golden/verbatim_subsuper.docx view

binary file changed (10438 → 10444 bytes)

test/docx/lists.native view
@@ -2,7 +2,7 @@ ,OrderedList (1,Decimal,Period)  [[Para [Str "one"]]  ,[Para [Str "two"]-  ,OrderedList (1,LowerAlpha,DefaultDelim)+  ,OrderedList (1,LowerAlpha,Period)    [[Para [Str "a"]]    ,[Para [Str "b"]]]]] ,BulletList
test/docx/sdt_elements.native view
@@ -5,11 +5,11 @@  ,(AlignDefault,ColWidth 0.5586085939783689)]  (TableHead ("",[],[])  [Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+   [Cell ("",[],[]) AlignCenter (RowSpan 1) (ColSpan 1)     [Plain [Strong [Str "col1Header"]]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+   ,Cell ("",[],[]) AlignCenter (RowSpan 1) (ColSpan 1)     [Plain [Strong [Str "col2Header"]]]-   ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+   ,Cell ("",[],[]) AlignCenter (RowSpan 1) (ColSpan 1)     [Plain [Strong [Str "col3Header"]]]]])  [(TableBody ("",[],[]) (RowHeadColumns 0)   []
test/docx/table_captions_no_field.docx view

binary file changed (40482 → 40487 bytes)

test/docx/table_header_rowspan.native view
@@ -1,6 +1,6 @@ [Table ("",[],[]) (Caption Nothing  [])- [(AlignDefault,ColWidth 0.30701754385964913)+ [(AlignLeft,ColWidth 0.30701754385964913)  ,(AlignDefault,ColWidth 0.1364522417153996)  ,(AlignDefault,ColWidth 0.10009746588693957)  ,(AlignDefault,ColWidth 9.707602339181287e-2)@@ -32,7 +32,7 @@  [(TableBody ("",[],[]) (RowHeadColumns 0)   []   [Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+   [Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)     [Plain [Str "1"]]    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)     [Plain [Str "2"]]@@ -49,7 +49,7 @@    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)     [Plain [Str "8"]]]   ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+   [Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)     [Plain [Str "1"]]    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)     [Plain [Str "2"]]@@ -66,7 +66,7 @@    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)     [Plain [Str "8"]]]   ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+   [Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)     [Plain [Str "1"]]    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)     [Plain [Str "2"]]@@ -83,7 +83,7 @@    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)     [Plain [Str "8"]]]   ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+   [Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)     [Plain [Str "1"]]    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)     [Plain [Str "2"]]@@ -100,7 +100,7 @@    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)     [Plain [Str "8"]]]   ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+   [Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)     [Plain [Str "1"]]    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)     [Plain [Str "2"]]@@ -117,7 +117,7 @@    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)     [Plain [Str "8"]]]   ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+   [Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)     [Plain [Str "1"]]    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)     [Plain [Str "2"]]@@ -134,7 +134,7 @@    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)     [Plain [Str "8"]]]   ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+   [Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)     [Plain [Str "1"]]    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)     [Plain [Str "2"]]@@ -151,7 +151,7 @@    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)     [Plain [Str "8"]]]   ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+   [Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)     [Plain [Str "1"]]    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)     [Plain [Str "2"]]@@ -168,7 +168,7 @@    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)     [Plain [Str "8"]]]   ,Row ("",[],[])-   [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+   [Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)     [Plain [Str "1"]]    ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)     [Plain [Str "2"]]
+ test/docx/task_list.docx view

binary file changed (absent → 10749 bytes)

+ test/docx/task_list.native view
@@ -0,0 +1,40 @@+[ BulletList+    [ [ Para [ Str "\9744" , Space , Str "Unchecked" ] ]+    , [ Para [ Str "\9746" , Space , Str "Checked" ]+      , Para+          [ Str "with"+          , Space+          , Str "continuation"+          , Space+          , Str "paragraph"+          ]+      ]+    , [ Para [ Str "\9744" , Space , Str "Unchecked" ]+      , BulletList+          [ [ Plain+                [ Str "\9746"+                , Space+                , Str "Checked"+                , Space+                , Str "sublist"+                ]+            , BulletList+                [ [ Plain+                      [ Str "\9744"+                      , Space+                      , Str "Unchecked"+                      , Space+                      , Str "subsublist"+                      ]+                  , OrderedList+                      ( 1 , Decimal , Period )+                      [ [ Plain [ Str "Numbered" , Space , Str "child" ]+                        ]+                      ]+                  ]+                ]+            ]+          ]+      ]+    ]+]
test/tables.djot view
@@ -44,11 +44,13 @@  Table without column headers: +|----:|:----|:---:|----:| |  12 | 12  | 12  |  12 | | 123 | 123 | 123 | 123 | |   1 | 1   |  1  |   1 |  Multiline table without column headers: +|:------:|:----|-----:|-----------------------------------------------------| | First  | row | 12.0 | Example of a row that spans multiple lines.           | | Second | row |  5.0 | Here's another one. Note the blank line between rows. |
test/tables.html4 view
@@ -2,7 +2,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>@@ -10,19 +10,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td> <td>12</td> </tr>-<tr class="even">+<tr> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td> <td>123</td> </tr>-<tr class="odd">+<tr> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>@@ -33,7 +33,7 @@ <p>Simple table without caption:</p> <table> <thead>-<tr class="header">+<tr> <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>@@ -41,19 +41,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td> <td>12</td> </tr>-<tr class="even">+<tr> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td> <td>123</td> </tr>-<tr class="odd">+<tr> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>@@ -65,7 +65,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>@@ -73,19 +73,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td> <td>12</td> </tr>-<tr class="even">+<tr> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td> <td>123</td> </tr>-<tr class="odd">+<tr> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>@@ -103,7 +103,7 @@ <col width="35%" /> </colgroup> <thead>-<tr class="header">+<tr> <th align="center">Centered Header</th> <th align="left">Left Aligned</th> <th align="right">Right Aligned</th>@@ -111,13 +111,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="center">First</td> <td align="left">row</td> <td align="right">12.0</td> <td align="left">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td align="center">Second</td> <td align="left">row</td> <td align="right">5.0</td>@@ -134,7 +134,7 @@ <col width="35%" /> </colgroup> <thead>-<tr class="header">+<tr> <th align="center">Centered Header</th> <th align="left">Left Aligned</th> <th align="right">Right Aligned</th>@@ -142,13 +142,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="center">First</td> <td align="left">row</td> <td align="right">12.0</td> <td align="left">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td align="center">Second</td> <td align="left">row</td> <td align="right">5.0</td>@@ -159,19 +159,19 @@ <p>Table without column headers:</p> <table> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td> <td align="right">12</td> </tr>-<tr class="even">+<tr> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td> <td align="right">123</td> </tr>-<tr class="odd">+<tr> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>@@ -188,13 +188,13 @@ <col width="35%" /> </colgroup> <tbody>-<tr class="odd">+<tr> <td align="center">First</td> <td align="left">row</td> <td align="right">12.0</td> <td>Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td align="center">Second</td> <td align="left">row</td> <td align="right">5.0</td>
test/tables.html5 view
@@ -2,7 +2,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th style="text-align: right;">Right</th> <th style="text-align: left;">Left</th> <th style="text-align: center;">Center</th>@@ -10,19 +10,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: right;">12</td> <td style="text-align: left;">12</td> <td style="text-align: center;">12</td> <td>12</td> </tr>-<tr class="even">+<tr> <td style="text-align: right;">123</td> <td style="text-align: left;">123</td> <td style="text-align: center;">123</td> <td>123</td> </tr>-<tr class="odd">+<tr> <td style="text-align: right;">1</td> <td style="text-align: left;">1</td> <td style="text-align: center;">1</td>@@ -33,7 +33,7 @@ <p>Simple table without caption:</p> <table> <thead>-<tr class="header">+<tr> <th style="text-align: right;">Right</th> <th style="text-align: left;">Left</th> <th style="text-align: center;">Center</th>@@ -41,19 +41,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: right;">12</td> <td style="text-align: left;">12</td> <td style="text-align: center;">12</td> <td>12</td> </tr>-<tr class="even">+<tr> <td style="text-align: right;">123</td> <td style="text-align: left;">123</td> <td style="text-align: center;">123</td> <td>123</td> </tr>-<tr class="odd">+<tr> <td style="text-align: right;">1</td> <td style="text-align: left;">1</td> <td style="text-align: center;">1</td>@@ -65,7 +65,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th style="text-align: right;">Right</th> <th style="text-align: left;">Left</th> <th style="text-align: center;">Center</th>@@ -73,19 +73,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: right;">12</td> <td style="text-align: left;">12</td> <td style="text-align: center;">12</td> <td>12</td> </tr>-<tr class="even">+<tr> <td style="text-align: right;">123</td> <td style="text-align: left;">123</td> <td style="text-align: center;">123</td> <td>123</td> </tr>-<tr class="odd">+<tr> <td style="text-align: right;">1</td> <td style="text-align: left;">1</td> <td style="text-align: center;">1</td>@@ -103,7 +103,7 @@ <col style="width: 35%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: center;">Centered Header</th> <th style="text-align: left;">Left Aligned</th> <th style="text-align: right;">Right Aligned</th>@@ -111,13 +111,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: center;">First</td> <td style="text-align: left;">row</td> <td style="text-align: right;">12.0</td> <td style="text-align: left;">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td style="text-align: center;">Second</td> <td style="text-align: left;">row</td> <td style="text-align: right;">5.0</td>@@ -135,7 +135,7 @@ <col style="width: 35%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: center;">Centered Header</th> <th style="text-align: left;">Left Aligned</th> <th style="text-align: right;">Right Aligned</th>@@ -143,13 +143,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: center;">First</td> <td style="text-align: left;">row</td> <td style="text-align: right;">12.0</td> <td style="text-align: left;">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td style="text-align: center;">Second</td> <td style="text-align: left;">row</td> <td style="text-align: right;">5.0</td>@@ -161,19 +161,19 @@ <p>Table without column headers:</p> <table> <tbody>-<tr class="odd">+<tr> <td style="text-align: right;">12</td> <td style="text-align: left;">12</td> <td style="text-align: center;">12</td> <td style="text-align: right;">12</td> </tr>-<tr class="even">+<tr> <td style="text-align: right;">123</td> <td style="text-align: left;">123</td> <td style="text-align: center;">123</td> <td style="text-align: right;">123</td> </tr>-<tr class="odd">+<tr> <td style="text-align: right;">1</td> <td style="text-align: left;">1</td> <td style="text-align: center;">1</td>@@ -190,13 +190,13 @@ <col style="width: 35%" /> </colgroup> <tbody>-<tr class="odd">+<tr> <td style="text-align: center;">First</td> <td style="text-align: left;">row</td> <td style="text-align: right;">12.0</td> <td>Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td style="text-align: center;">Second</td> <td style="text-align: left;">row</td> <td style="text-align: right;">5.0</td>
test/tables.latex view
@@ -53,10 +53,10 @@ Multiline table with caption:  \begin{longtable}[]{@{}-  >{\centering\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1500}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1375}}-  >{\raggedleft\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1625}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.3500}}@{}}+  >{\centering\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1500}}+  >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1375}}+  >{\raggedleft\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1625}}+  >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3500}}@{}} \caption{Here's the caption. It may span multiple lines.}\tabularnewline \toprule\noalign{} \begin{minipage}[b]{\linewidth}\centering@@ -91,10 +91,10 @@ Multiline table without caption:  \begin{longtable}[]{@{}-  >{\centering\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1500}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1375}}-  >{\raggedleft\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1625}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.3500}}@{}}+  >{\centering\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1500}}+  >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1375}}+  >{\raggedleft\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1625}}+  >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3500}}@{}} \toprule\noalign{} \begin{minipage}[b]{\linewidth}\centering Centered Header@@ -128,10 +128,10 @@ Multiline table without column headers:  \begin{longtable}[]{@{}-  >{\centering\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1500}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1375}}-  >{\raggedleft\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1625}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.3500}}@{}}+  >{\centering\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1500}}+  >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1375}}+  >{\raggedleft\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1625}}+  >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3500}}@{}} \toprule\noalign{} \endhead \bottomrule\noalign{}
test/tables.textile view
@@ -3,7 +3,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>@@ -11,19 +11,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td> <td align="left">12</td> </tr>-<tr class="even">+<tr> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td> <td align="left">123</td> </tr>-<tr class="odd">+<tr> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>@@ -44,7 +44,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>@@ -52,19 +52,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td> <td align="left">12</td> </tr>-<tr class="even">+<tr> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td> <td align="left">123</td> </tr>-<tr class="odd">+<tr> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>@@ -82,7 +82,7 @@ <col width="16%" /> <col width="35%" /> <thead>-<tr class="header">+<tr> <th align="center">Centered Header</th> <th align="left">Left Aligned</th> <th align="right">Right Aligned</th>@@ -90,13 +90,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="center">First</td> <td align="left">row</td> <td align="right">12.0</td> <td align="left">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td align="center">Second</td> <td align="left">row</td> <td align="right">5.0</td>@@ -113,7 +113,7 @@ <col width="16%" /> <col width="35%" /> <thead>-<tr class="header">+<tr> <th align="center">Centered Header</th> <th align="left">Left Aligned</th> <th align="right">Right Aligned</th>@@ -121,13 +121,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="center">First</td> <td align="left">row</td> <td align="right">12.0</td> <td align="left">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td align="center">Second</td> <td align="left">row</td> <td align="right">5.0</td>@@ -150,13 +150,13 @@ <col width="16%" /> <col width="35%" /> <tbody>-<tr class="odd">+<tr> <td align="center">First</td> <td align="left">row</td> <td align="right">12.0</td> <td align="left">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td align="center">Second</td> <td align="left">row</td> <td align="right">5.0</td>
test/tables/nordics.html4 view
@@ -7,7 +7,7 @@ <col width="20%" /> </colgroup> <thead class="simple-head">-<tr class="header">+<tr> <th align="center">Name</th> <th align="center">Capital</th> <th align="center">Population<br />@@ -17,38 +17,38 @@ </tr> </thead> <tbody class="souvereign-states">-<tr class="odd country">+<tr class="country"> <th align="center">Denmark</th> <td align="left">Copenhagen</td> <td align="left">5,809,502</td> <td align="left">43,094</td> </tr>-<tr class="even country">+<tr class="country"> <th align="center">Finland</th> <td align="left">Helsinki</td> <td align="left">5,537,364</td> <td align="left">338,145</td> </tr>-<tr class="odd country">+<tr class="country"> <th align="center">Iceland</th> <td align="left">Reykjavik</td> <td align="left">343,518</td> <td align="left">103,000</td> </tr>-<tr class="even country">+<tr class="country"> <th align="center">Norway</th> <td align="left">Oslo</td> <td align="left">5,372,191</td> <td align="left">323,802</td> </tr>-<tr class="odd country">+<tr class="country"> <th align="center">Sweden</th> <td align="left">Stockholm</td> <td align="left">10,313,447</td> <td align="left">450,295</td> </tr> </tbody><tfoot>-<tr id="summary" class="even">+<tr id="summary"> <td align="center">Total</td> <td align="left"></td> <td id="total-population" align="left">27,376,022</td>
test/tables/nordics.html5 view
@@ -7,7 +7,7 @@ <col style="width: 20%" /> </colgroup> <thead class="simple-head">-<tr class="header">+<tr> <th style="text-align: center;">Name</th> <th style="text-align: center;">Capital</th> <th style="text-align: center;">Population<br />@@ -17,38 +17,38 @@ </tr> </thead> <tbody class="souvereign-states">-<tr class="odd country">+<tr class="country"> <th style="text-align: center;">Denmark</th> <td style="text-align: left;">Copenhagen</td> <td style="text-align: left;">5,809,502</td> <td style="text-align: left;">43,094</td> </tr>-<tr class="even country">+<tr class="country"> <th style="text-align: center;">Finland</th> <td style="text-align: left;">Helsinki</td> <td style="text-align: left;">5,537,364</td> <td style="text-align: left;">338,145</td> </tr>-<tr class="odd country">+<tr class="country"> <th style="text-align: center;">Iceland</th> <td style="text-align: left;">Reykjavik</td> <td style="text-align: left;">343,518</td> <td style="text-align: left;">103,000</td> </tr>-<tr class="even country">+<tr class="country"> <th style="text-align: center;">Norway</th> <td style="text-align: left;">Oslo</td> <td style="text-align: left;">5,372,191</td> <td style="text-align: left;">323,802</td> </tr>-<tr class="odd country">+<tr class="country"> <th style="text-align: center;">Sweden</th> <td style="text-align: left;">Stockholm</td> <td style="text-align: left;">10,313,447</td> <td style="text-align: left;">450,295</td> </tr> </tbody><tfoot>-<tr id="summary" class="even">+<tr id="summary"> <td style="text-align: center;">Total</td> <td style="text-align: left;"></td> <td id="total-population" style="text-align: left;">27,376,022</td>
test/tables/nordics.latex view
@@ -1,8 +1,8 @@ \begin{longtable}[]{@{}-  >{\centering\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.3000}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.3000}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.2000}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.2000}}@{}}+  >{\centering\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3000}}+  >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3000}}+  >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.2000}}+  >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.2000}}@{}} \caption[Nordic countries]{States belonging to the \emph{Nordics.}}\label{nordics}\tabularnewline \toprule\noalign{}
test/tables/planets.html4 view
@@ -1,7 +1,7 @@ <table> <caption><p>Data about the planets of our solar system.</p></caption> <thead>-<tr class="header">+<tr> <th colspan="2" align="center"></th> <th>Name</th> <th align="right">Mass (10^24kg)</th>@@ -16,7 +16,7 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <th colspan="2" rowspan="4" align="center">Terrestrial planets</th> <th>Mercury</th> <td align="right">0.330</td>@@ -29,7 +29,7 @@ <td align="right">0</td> <td>Closest to the Sun</td> </tr>-<tr class="even">+<tr> <th>Venus</th> <td align="right">4.87</td> <td align="right">12,104</td>@@ -41,7 +41,7 @@ <td align="right">0</td> <td></td> </tr>-<tr class="odd">+<tr> <th>Earth</th> <td align="right">5.97</td> <td align="right">12,756</td>@@ -53,7 +53,7 @@ <td align="right">1</td> <td>Our world</td> </tr>-<tr class="even">+<tr> <th>Mars</th> <td align="right">0.642</td> <td align="right">6,792</td>@@ -65,7 +65,7 @@ <td align="right">2</td> <td>The red planet</td> </tr>-<tr class="odd">+<tr> <th rowspan="4" align="center">Jovian planets</th> <th rowspan="2" align="center">Gas giants</th> <th>Jupiter</th>@@ -79,7 +79,7 @@ <td align="right">67</td> <td>The largest planet</td> </tr>-<tr class="even">+<tr> <th>Saturn</th> <td align="right">568</td> <td align="right">120,536</td>@@ -91,7 +91,7 @@ <td align="right">62</td> <td></td> </tr>-<tr class="odd">+<tr> <th rowspan="2" align="center">Ice giants</th> <th>Uranus</th> <td align="right">86.8</td>@@ -104,7 +104,7 @@ <td align="right">27</td> <td></td> </tr>-<tr class="even">+<tr> <th>Neptune</th> <td align="right">102</td> <td align="right">49,528</td>@@ -116,7 +116,7 @@ <td align="right">14</td> <td></td> </tr>-<tr class="odd">+<tr> <th colspan="2" align="center">Dwarf planets</th> <th>Pluto</th> <td align="right">0.0146</td>
test/tables/planets.html5 view
@@ -1,7 +1,7 @@ <table> <caption><p>Data about the planets of our solar system.</p></caption> <thead>-<tr class="header">+<tr> <th colspan="2" style="text-align: center;"></th> <th>Name</th> <th style="text-align: right;">Mass (10^24kg)</th>@@ -16,7 +16,7 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <th colspan="2" rowspan="4" style="text-align: center;">Terrestrial planets</th> <th>Mercury</th> <td style="text-align: right;">0.330</td>@@ -29,7 +29,7 @@ <td style="text-align: right;">0</td> <td>Closest to the Sun</td> </tr>-<tr class="even">+<tr> <th>Venus</th> <td style="text-align: right;">4.87</td> <td style="text-align: right;">12,104</td>@@ -41,7 +41,7 @@ <td style="text-align: right;">0</td> <td></td> </tr>-<tr class="odd">+<tr> <th>Earth</th> <td style="text-align: right;">5.97</td> <td style="text-align: right;">12,756</td>@@ -53,7 +53,7 @@ <td style="text-align: right;">1</td> <td>Our world</td> </tr>-<tr class="even">+<tr> <th>Mars</th> <td style="text-align: right;">0.642</td> <td style="text-align: right;">6,792</td>@@ -65,7 +65,7 @@ <td style="text-align: right;">2</td> <td>The red planet</td> </tr>-<tr class="odd">+<tr> <th rowspan="4" style="text-align: center;">Jovian planets</th> <th rowspan="2" style="text-align: center;">Gas giants</th> <th>Jupiter</th>@@ -79,7 +79,7 @@ <td style="text-align: right;">67</td> <td>The largest planet</td> </tr>-<tr class="even">+<tr> <th>Saturn</th> <td style="text-align: right;">568</td> <td style="text-align: right;">120,536</td>@@ -91,7 +91,7 @@ <td style="text-align: right;">62</td> <td></td> </tr>-<tr class="odd">+<tr> <th rowspan="2" style="text-align: center;">Ice giants</th> <th>Uranus</th> <td style="text-align: right;">86.8</td>@@ -104,7 +104,7 @@ <td style="text-align: right;">27</td> <td></td> </tr>-<tr class="even">+<tr> <th>Neptune</th> <td style="text-align: right;">102</td> <td style="text-align: right;">49,528</td>@@ -116,7 +116,7 @@ <td style="text-align: right;">14</td> <td></td> </tr>-<tr class="odd">+<tr> <th colspan="2" style="text-align: center;">Dwarf planets</th> <th>Pluto</th> <td style="text-align: right;">0.0146</td>
test/tables/students.html4 view
@@ -5,49 +5,49 @@ <col width="50%" /> </colgroup> <thead>-<tr class="header">+<tr> <th align="center">Student ID</th> <th align="center">Name</th> </tr> </thead> <tbody class="souvereign-states">-<tr class="odd">+<tr> <th colspan="2" align="left">Computer Science</th> </tr> -<tr class="odd">+<tr> <td align="left">3741255</td> <td align="left">Jones, Martha</td> </tr>-<tr class="even">+<tr> <td align="left">4077830</td> <td align="left">Pierce, Benjamin</td> </tr>-<tr class="odd">+<tr> <td align="left">5151701</td> <td align="left">Kirk, James</td> </tr> </tbody> <tbody>-<tr class="odd">+<tr> <th colspan="2" align="left">Russian Literature</th> </tr> -<tr class="odd">+<tr> <td align="left">3971244</td> <td align="left">Nim, Victor</td> </tr> </tbody> <tbody>-<tr class="odd">+<tr> <th colspan="2" align="left">Astrophysics</th> </tr> -<tr class="odd">+<tr> <td align="left">4100332</td> <td align="left">Petrov, Alexandra</td> </tr>-<tr class="even">+<tr> <td align="left">4100332</td> <td align="left">Toyota, Hiroko</td> </tr>
test/tables/students.html5 view
@@ -5,49 +5,49 @@ <col style="width: 50%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: center;">Student ID</th> <th style="text-align: center;">Name</th> </tr> </thead> <tbody class="souvereign-states">-<tr class="odd">+<tr> <th colspan="2" style="text-align: left;">Computer Science</th> </tr> -<tr class="odd">+<tr> <td style="text-align: left;">3741255</td> <td style="text-align: left;">Jones, Martha</td> </tr>-<tr class="even">+<tr> <td style="text-align: left;">4077830</td> <td style="text-align: left;">Pierce, Benjamin</td> </tr>-<tr class="odd">+<tr> <td style="text-align: left;">5151701</td> <td style="text-align: left;">Kirk, James</td> </tr> </tbody> <tbody>-<tr class="odd">+<tr> <th colspan="2" style="text-align: left;">Russian Literature</th> </tr> -<tr class="odd">+<tr> <td style="text-align: left;">3971244</td> <td style="text-align: left;">Nim, Victor</td> </tr> </tbody> <tbody>-<tr class="odd">+<tr> <th colspan="2" style="text-align: left;">Astrophysics</th> </tr> -<tr class="odd">+<tr> <td style="text-align: left;">4100332</td> <td style="text-align: left;">Petrov, Alexandra</td> </tr>-<tr class="even">+<tr> <td style="text-align: left;">4100332</td> <td style="text-align: left;">Toyota, Hiroko</td> </tr>
test/tables/students.latex view
@@ -1,6 +1,6 @@ \begin{longtable}[]{@{}-  >{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{0.5000}}-  >{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{0.5000}}@{}}+  >{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{0.5000}}+  >{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{0.5000}}@{}} \caption{List of Students}\label{students}\tabularnewline \toprule\noalign{} \begin{minipage}[b]{\linewidth}\centering@@ -20,15 +20,15 @@ \endhead \bottomrule\noalign{} \endlastfoot-\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{%+\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{% Computer Science} \\ 3741255 & Jones, Martha \\ 4077830 & Pierce, Benjamin \\ 5151701 & Kirk, James \\-\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{%+\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{% Russian Literature} \\ 3971244 & Nim, Victor \\-\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{%+\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{% Astrophysics} \\ 4100332 & Petrov, Alexandra \\ 4100332 & Toyota, Hiroko \\
test/typst-reader.native view
@@ -203,7 +203,8 @@               [ Underline                   [ Link                       ( "" , [] , [] )-                      [ Strong+                      [ SoftBreak+                      , Strong                           [ Str "Typst"                           , Space                           , Str "Math"@@ -212,6 +213,7 @@                           , Space                           , Str "Undergrads"                           ]+                      , SoftBreak                       ]                       ( "https://github.com/johanvx/typst-undergradmath"                       , ""
test/writer.context view
@@ -13,7 +13,6 @@ \setupinteractionscreen[option={bookmark,title}]  \setuppagenumbering[location={footer,middle}]-\setupbackend[export=yes] \setupstructure[state=start,method=auto]  % use microtypography
test/writer.latex view
@@ -39,15 +39,17 @@ \usepackage{xcolor} \usepackage{graphicx} \makeatletter-\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi}-\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi}-\makeatother-% Scale images if necessary, so that they will not overflow the page-% margins by default, and it is still possible to overwrite the defaults-% using explicit options in \includegraphics[width, height, ...]{}-\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio}+\newsavebox\pandoc@box+\newcommand*\pandocbounded[1]{% scales image to fit in text height/width+  \sbox\pandoc@box{#1}%+  \Gscale@div\@tempa{\textheight}{\dimexpr\ht\pandoc@box+\dp\pandoc@box\relax}%+  \Gscale@div\@tempb{\linewidth}{\wd\pandoc@box}%+  \ifdim\@tempb\p@<\@tempa\p@\let\@tempa\@tempb\fi% select the smaller of both+  \ifdim\@tempa\p@<\p@\scalebox{\@tempa}{\usebox\pandoc@box}%+  \else\usebox{\pandoc@box}%+  \fi%+} % Set default figure placement to htbp-\makeatletter \def\fps@figure{htbp} \makeatother \ifLuaTeX@@ -60,9 +62,6 @@ \providecommand{\tightlist}{%   \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} \setcounter{secnumdepth}{-\maxdimen} % remove section numbering-\ifLuaTeX-  \usepackage{selnolig}  % disable illegal ligatures-\fi \usepackage{bookmark} \IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available \urlstyle{same}@@ -925,11 +924,12 @@  \begin{figure} \centering-\includegraphics{lalune.jpg}+\pandocbounded{\includegraphics[keepaspectratio]{lalune.jpg}} \caption{lalune} \end{figure} -Here is a movie \includegraphics{movie.jpg} icon.+Here is a movie \pandocbounded{\includegraphics[keepaspectratio]{movie.jpg}}+icon.  \begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} 
test/writer.texinfo view
@@ -1,4 +1,6 @@-\input texinfo+\input texinfo  @c -*-texinfo-*-+@settitle Pandoc Test Suite+ @documentencoding UTF-8  @macro textstrikeout{text}@@ -48,23 +50,20 @@  @node Headers @chapter Headers-@anchor{#headers}  @menu-* Level 2 with an embedded link::+* Level 2 with an @uref{/url,embedded link}:: @end menu -@node Level 2 with an embedded link+@node Level 2 with an @uref{/url,embedded link} @section Level 2 with an @uref{/url,embedded link}-@anchor{#level-2-with-an-embedded-link}  @menu-* Level 3 with emphasis::+* Level 3 with @emph{emphasis}:: @end menu -@node Level 3 with emphasis+@node Level 3 with @emph{emphasis} @subsection Level 3 with @emph{emphasis}-@anchor{#level-3-with-emphasis}  @menu * Level 4::@@ -72,21 +71,18 @@  @node Level 4 @subsubsection Level 4-@anchor{#level-4} Level 5  @node Level 1 @chapter Level 1-@anchor{#level-1}  @menu-* Level 2 with emphasis::+* Level 2 with @emph{emphasis}:: * Level 2:: @end menu -@node Level 2 with emphasis+@node Level 2 with @emph{emphasis} @section Level 2 with @emph{emphasis}-@anchor{#level-2-with-emphasis}  @menu * Level 3::@@ -94,12 +90,10 @@  @node Level 3 @subsection Level 3-@anchor{#level-3} with no blank line  @node Level 2 @section Level 2-@anchor{#level-2} with no blank line  @iftex@@ -111,7 +105,6 @@  @node Paragraphs @chapter Paragraphs-@anchor{#paragraphs} Here's a regular paragraph.  In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item.@@ -132,7 +125,6 @@  @node Block Quotes @chapter Block Quotes-@anchor{#block-quotes} E-mail style:  @quotation@@ -178,7 +170,6 @@  @node Code Blocks @chapter Code Blocks-@anchor{#code-blocks} Code:  @verbatim@@ -208,7 +199,6 @@  @node Lists @chapter Lists-@anchor{#lists}  @menu * Unordered::@@ -220,7 +210,6 @@  @node Unordered @section Unordered-@anchor{#unordered} Asterisks tight:  @itemize@@ -298,7 +287,6 @@  @node Ordered @section Ordered-@anchor{#ordered} Tight:  @enumerate @@ -367,7 +355,6 @@  @node Nested @section Nested-@anchor{#nested} @itemize @item Tab@@ -428,7 +415,6 @@  @node Tabs and spaces @section Tabs and spaces-@anchor{#tabs-and-spaces} @itemize @item this is a list item indented with tabs@@ -449,7 +435,6 @@  @node Fancy list markers @section Fancy list markers-@anchor{#fancy-list-markers} @enumerate 2 @item begins with 2@@ -526,7 +511,6 @@  @node Definition Lists @chapter Definition Lists-@anchor{#definition-lists} Tight using spaces:  @table @asis@@ -648,7 +632,6 @@  @node HTML Blocks @chapter HTML Blocks-@anchor{#html-blocks} Simple block on one line:  foo@@ -709,7 +692,6 @@  @node Inline Markup @chapter Inline Markup-@anchor{#inline-markup} This is @emph{emphasized}, and so @emph{is this}.  This is @strong{strong}, and so @strong{is this}.@@ -744,7 +726,6 @@  @node Smart quotes ellipses dashes @chapter Smart quotes, ellipses, dashes-@anchor{#smart-quotes-ellipses-dashes} ``Hello,'' said the spider. ```Shelob' is my name.''  `A', `B', and `C' are letters.@@ -771,7 +752,6 @@  @node LaTeX @chapter LaTeX-@anchor{#latex} @itemize @item @tex@@ -826,7 +806,6 @@  @node Special Characters @chapter Special Characters-@anchor{#special-characters} Here is some unicode:  @itemize@@ -893,7 +872,6 @@  @node Links @chapter Links-@anchor{#links}  @menu * Explicit::@@ -904,7 +882,6 @@  @node Explicit @section Explicit-@anchor{#explicit} Just a @uref{/url/,URL}.  @uref{/url/,URL and title}.@@ -925,7 +902,6 @@  @node Reference @section Reference-@anchor{#reference} Foo @uref{/url/,bar}.  With @uref{/url/,embedded [brackets]}.@@ -950,7 +926,6 @@  @node With ampersands @section With ampersands-@anchor{#with-ampersands} Here's a @uref{http://example.com/?foo=1&bar=2,link with an ampersand in the URL}. @@ -962,7 +937,6 @@  @node Autolinks @section Autolinks-@anchor{#autolinks} With an ampersand: @url{http://example.com/?foo=1&bar=2}  @itemize@@ -974,7 +948,7 @@ It should. @end itemize -An e-mail address: @uref{mailto:nobody@@nowhere.net,nobody@@nowhere.net}+An e-mail address: @uref{mailto:nobody@@nowhere.net,nobody@@nowherenet}  @quotation Blockquoted: @url{http://example.com/}@@ -994,7 +968,6 @@  @node Images @chapter Images-@anchor{#images} From ``Voyage dans la Lune'' by Georges Melies (1902):  @float@@ -1012,7 +985,6 @@  @node Footnotes @chapter Footnotes-@anchor{#footnotes} Here is a footnote reference,@footnote{Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.} and another.@footnote{Here's the long note. This one contains multiple blocks.
test/writer.typst view
@@ -20,8 +20,20 @@   stroke: none ) +#let content-to-string(content) = {+  if content.has("text") {+    content.text+  } else if content.has("children") {+    content.children.map(content-to-string).join("")+  } else if content.has("body") {+    content-to-string(content.body)+  } else if content == [ ] {+    " "+  }+} #let conf(   title: none,+  subtitle: none,   authors: (),   keywords: (),   date: none,@@ -38,7 +50,7 @@ ) = {   set document(     title: title,-    author: authors.map(author => author.name),+    author: authors.map(author => content-to-string(author.name)),     keywords: keywords,   )   set page(@@ -56,6 +68,10 @@   if title != none {     align(center)[#block(inset: 2em)[       #text(weight: "bold", size: 1.5em)[#title]+      #(if subtitle != none {+        parbreak()+        text(weight: "bold", size: 1.25em)[#subtitle]+      })     ]]   } @@ -96,14 +112,14 @@ #show: doc => conf(   title: [Pandoc Test Suite],   authors: (-    ( name: "John MacFarlane",+    ( name: [John MacFarlane],       affiliation: "",       email: "" ),-    ( name: "Anonymous",+    ( name: [Anonymous],       affiliation: "",       email: "" ),     ),-  date: "July 17, 2006",+  date: [July 17, 2006],   cols: 1,   doc, )
test/writers-lang-and-dir.context view
@@ -11,7 +11,6 @@ \setupinteractionscreen[option={bookmark,title}]  \setuppagenumbering[location={footer,middle}]-\setupbackend[export=yes] \setupstructure[state=start,method=auto]  % use microtypography
test/writers-lang-and-dir.latex view
@@ -55,7 +55,7 @@ \let\LanguageShortHands\languageshorthands \def\languageshorthands#1{} \ifLuaTeX-  \usepackage{selnolig}  % disable illegal ligatures+  \usepackage[english,german]{selnolig} % disable illegal ligatures \fi \ifPDFTeX   \TeXXeTstate=1