panache-cli 2.54.0__tar.gz → 2.56.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. {panache_cli-2.54.0 → panache_cli-2.56.0}/Cargo.lock +10 -7
  2. {panache_cli-2.54.0 → panache_cli-2.56.0}/Cargo.toml +3 -11
  3. {panache_cli-2.54.0 → panache_cli-2.56.0}/PKG-INFO +1 -1
  4. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/CHANGELOG.md +28 -0
  5. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/Cargo.toml +10 -2
  6. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/config.rs +76 -1
  7. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/inline.rs +97 -70
  8. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/lists.rs +75 -0
  9. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/math/STYLE.md +48 -11
  10. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/math/linebreak.rs +158 -38
  11. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/math/operators.rs +1 -1
  12. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/math/render.rs +57 -4
  13. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/math.rs +4 -3
  14. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/tables.rs +11 -7
  15. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/CHANGELOG.md +10 -0
  16. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/Cargo.toml +1 -1
  17. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/pandoc_ast.rs +38 -1
  18. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/block_dispatcher.rs +20 -0
  19. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/code_blocks.rs +14 -32
  20. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tables.rs +61 -0
  21. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/core.rs +130 -0
  22. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/attributes.rs +84 -0
  23. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/config/types.rs +50 -6
  24. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/config.rs +33 -0
  25. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/formatter.rs +1 -0
  26. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/main.rs +39 -3
  27. {panache_cli-2.54.0 → panache_cli-2.56.0}/LICENSE +0 -0
  28. {panache_cli-2.54.0 → panache_cli-2.56.0}/README.md +0 -0
  29. {panache_cli-2.54.0 → panache_cli-2.56.0}/build.rs +0 -0
  30. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/README.md +0 -0
  31. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/directives.rs +0 -0
  32. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/blockquotes.rs +0 -0
  33. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/code_blocks.rs +0 -0
  34. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/core.rs +0 -0
  35. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/fenced_divs.rs +0 -0
  36. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/hashpipe.rs +0 -0
  37. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/headings.rs +0 -0
  38. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/indent_utils.rs +0 -0
  39. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/inline_layout.rs +0 -0
  40. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/metadata.rs +0 -0
  41. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/paragraphs.rs +0 -0
  42. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/sentence_wrap.rs +0 -0
  43. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/shortcodes.rs +0 -0
  44. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/smart.rs +0 -0
  45. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/utils.rs +0 -0
  46. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/yaml/STYLE.md +0 -0
  47. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/yaml/block_map.rs +0 -0
  48. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/yaml/block_sequence.rs +0 -0
  49. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/yaml/document.rs +0 -0
  50. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/yaml/flow.rs +0 -0
  51. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/yaml/options.rs +0 -0
  52. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/yaml/scalar.rs +0 -0
  53. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/yaml.rs +0 -0
  54. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter.rs +0 -0
  55. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/lib.rs +0 -0
  56. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/parser.rs +0 -0
  57. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/syntax.rs +0 -0
  58. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/utils.rs +0 -0
  59. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-formatter/src/yaml_engine.rs +0 -0
  60. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/README.md +0 -0
  61. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/build.rs +0 -0
  62. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/lib.rs +0 -0
  63. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/options.rs +0 -0
  64. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/blockquotes.rs +0 -0
  65. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/container_prefix.rs +0 -0
  66. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/definition_lists.rs +0 -0
  67. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/fenced_divs.rs +0 -0
  68. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/figures.rs +0 -0
  69. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/headings.rs +0 -0
  70. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/horizontal_rules.rs +0 -0
  71. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/html_blocks.rs +0 -0
  72. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/indented_code.rs +0 -0
  73. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/latex_envs.rs +0 -0
  74. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/line_blocks.rs +0 -0
  75. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/lists.rs +0 -0
  76. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/metadata.rs +0 -0
  77. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/paragraphs.rs +0 -0
  78. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/raw_blocks.rs +0 -0
  79. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/reference_links.rs +0 -0
  80. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tests/blanklines.rs +0 -0
  81. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tests/blockquotes.rs +0 -0
  82. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tests/code_blocks.rs +0 -0
  83. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tests/definition_lists.rs +0 -0
  84. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tests/headings.rs +0 -0
  85. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tests/helpers.rs +0 -0
  86. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tests/lists.rs +0 -0
  87. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tests/losslessness.rs +0 -0
  88. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tests/metadata_guards.rs +0 -0
  89. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks.rs +0 -0
  90. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/diagnostics.rs +0 -0
  91. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/bookdown.rs +0 -0
  92. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/bracketed_spans.rs +0 -0
  93. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/citations.rs +0 -0
  94. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/code_spans.rs +0 -0
  95. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/core.rs +0 -0
  96. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/emoji.rs +0 -0
  97. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/escapes.rs +0 -0
  98. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/inline_executable.rs +0 -0
  99. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/inline_footnotes.rs +0 -0
  100. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/inline_html.rs +0 -0
  101. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/inline_ir.rs +0 -0
  102. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/latex.rs +0 -0
  103. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/links.rs +0 -0
  104. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/mark.rs +0 -0
  105. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/math.rs +0 -0
  106. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/native_spans.rs +0 -0
  107. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/raw_inline.rs +0 -0
  108. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/refdef_map.rs +0 -0
  109. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/shortcodes.rs +0 -0
  110. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/sink.rs +0 -0
  111. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/strikeout.rs +0 -0
  112. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/subscript.rs +0 -0
  113. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/superscript.rs +0 -0
  114. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/tests.rs +0 -0
  115. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/uri-schemes.csv +0 -0
  116. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/wikilinks.rs +0 -0
  117. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines.rs +0 -0
  118. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/math.rs +0 -0
  119. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/chunk_options.rs +0 -0
  120. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/container_stack.rs +0 -0
  121. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/continuation.rs +0 -0
  122. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/helpers.rs +0 -0
  123. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/inline_emission.rs +0 -0
  124. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/list_item_buffer.rs +0 -0
  125. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/marker_utils.rs +0 -0
  126. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/text_buffer.rs +0 -0
  127. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/tree_copy.rs +0 -0
  128. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/yaml_regions.rs +0 -0
  129. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils.rs +0 -0
  130. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/yaml/cooking.rs +0 -0
  131. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/yaml/events.rs +0 -0
  132. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/yaml/model.rs +0 -0
  133. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/yaml/parser.rs +0 -0
  134. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/yaml/profile.rs +0 -0
  135. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/yaml/scanner.rs +0 -0
  136. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/yaml/validator.rs +0 -0
  137. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/yaml.rs +0 -0
  138. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser.rs +0 -0
  139. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/range_utils.rs +0 -0
  140. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/alerts.rs +0 -0
  141. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/ast.rs +0 -0
  142. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/attributes.rs +0 -0
  143. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/block_quotes.rs +0 -0
  144. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/blocks.rs +0 -0
  145. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/chunk_options.rs +0 -0
  146. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/citations.rs +0 -0
  147. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/code_blocks.rs +0 -0
  148. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/crossrefs.rs +0 -0
  149. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/definitions.rs +0 -0
  150. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/fenced_divs.rs +0 -0
  151. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/headings.rs +0 -0
  152. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/inlines.rs +0 -0
  153. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/kind.rs +0 -0
  154. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/links.rs +0 -0
  155. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/lists.rs +0 -0
  156. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/math.rs +0 -0
  157. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/raw_tex.rs +0 -0
  158. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/references.rs +0 -0
  159. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/shortcodes.rs +0 -0
  160. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/tables.rs +0 -0
  161. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/yaml.rs +0 -0
  162. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/yaml_ast.rs +0 -0
  163. {panache_cli-2.54.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax.rs +0 -0
  164. {panache_cli-2.54.0 → panache_cli-2.56.0}/pyproject.toml +0 -0
  165. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/bib/bibtex.rs +0 -0
  166. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/bib/csl_json.rs +0 -0
  167. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/bib/csl_yaml.rs +0 -0
  168. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/bib/index.rs +0 -0
  169. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/bib/ris.rs +0 -0
  170. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/bib.rs +0 -0
  171. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/cache.rs +0 -0
  172. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/cli.rs +0 -0
  173. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/config/formatter_presets.rs +0 -0
  174. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/config/types/schema_helpers.rs +0 -0
  175. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/diagnostic_renderer.rs +0 -0
  176. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/directives.rs +0 -0
  177. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/external_formatters_common.rs +0 -0
  178. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/external_formatters_sync.rs +0 -0
  179. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/external_tools_common.rs +0 -0
  180. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/includes.rs +0 -0
  181. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lib.rs +0 -0
  182. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/code_block_collector.rs +0 -0
  183. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/diagnostics.rs +0 -0
  184. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/external_linters/clippy.rs +0 -0
  185. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/external_linters/eslint.rs +0 -0
  186. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/external_linters/jarl.rs +0 -0
  187. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/external_linters/ruff.rs +0 -0
  188. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/external_linters/shellcheck.rs +0 -0
  189. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/external_linters/staticcheck.rs +0 -0
  190. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/external_linters.rs +0 -0
  191. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/external_linters_sync.rs +0 -0
  192. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/index.rs +0 -0
  193. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/metadata_diagnostics.rs +0 -0
  194. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/offsets.rs +0 -0
  195. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/adjacent_footnote_refs.rs +0 -0
  196. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/chunk_label_spaces.rs +0 -0
  197. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/citation_keys.rs +0 -0
  198. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/crossref_as_link_target.rs +0 -0
  199. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/duplicate_references.rs +0 -0
  200. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/emoji_aliases.rs +0 -0
  201. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/empty_list_item.rs +0 -0
  202. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/figure_crossref_captions.rs +0 -0
  203. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/footnote_ref_in_footnote_def.rs +0 -0
  204. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/heading_eaten_attrs.rs +0 -0
  205. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/heading_hierarchy.rs +0 -0
  206. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/heading_strip_comments_residue.rs +0 -0
  207. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/html_entities.rs +0 -0
  208. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/link_text_is_url.rs +0 -0
  209. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/math_content.rs +0 -0
  210. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/missing_chunk_labels.rs +0 -0
  211. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/stray_fenced_div_markers.rs +0 -0
  212. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/undefined_anchor.rs +0 -0
  213. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/undefined_references.rs +0 -0
  214. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules/unused_definitions.rs +0 -0
  215. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/rules.rs +0 -0
  216. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter/runner.rs +0 -0
  217. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/linter.rs +0 -0
  218. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/config.rs +0 -0
  219. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/context.rs +0 -0
  220. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/conversions.rs +0 -0
  221. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/dispatch.rs +0 -0
  222. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/documents.rs +0 -0
  223. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/global_state.rs +0 -0
  224. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/code_actions.rs +0 -0
  225. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/completion.rs +0 -0
  226. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/diagnostics.rs +0 -0
  227. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/document_links.rs +0 -0
  228. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/document_symbols.rs +0 -0
  229. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/file_rename.rs +0 -0
  230. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/file_watcher.rs +0 -0
  231. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/folding_ranges.rs +0 -0
  232. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/footnote_conversion.rs +0 -0
  233. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/formatting.rs +0 -0
  234. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/goto_definition.rs +0 -0
  235. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/heading_link_conversion.rs +0 -0
  236. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/hover.rs +0 -0
  237. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/link_conversion.rs +0 -0
  238. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/list_conversion.rs +0 -0
  239. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/prepare_rename.rs +0 -0
  240. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/references.rs +0 -0
  241. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/rename.rs +0 -0
  242. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/shortcode_args.rs +0 -0
  243. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers/workspace_symbols.rs +0 -0
  244. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/handlers.rs +0 -0
  245. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/helpers.rs +0 -0
  246. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/navigation.rs +0 -0
  247. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/symbols.rs +0 -0
  248. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/task_pool.rs +0 -0
  249. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/testing.rs +0 -0
  250. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp/uri_ext.rs +0 -0
  251. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/lsp.rs +0 -0
  252. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/metadata/bibliography.rs +0 -0
  253. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/metadata/citations.rs +0 -0
  254. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/metadata/project.rs +0 -0
  255. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/metadata/references.rs +0 -0
  256. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/metadata/yaml.rs +0 -0
  257. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/metadata.rs +0 -0
  258. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/parser.rs +0 -0
  259. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/range_utils.rs +0 -0
  260. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/salsa.rs +0 -0
  261. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/syntax.rs +0 -0
  262. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/utils.rs +0 -0
  263. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/yaml_engine.rs +0 -0
  264. {panache_cli-2.54.0 → panache_cli-2.56.0}/src/yaml_regions.rs +0 -0
@@ -1151,7 +1151,7 @@ checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e"
1151
1151
 
1152
1152
  [[package]]
1153
1153
  name = "panache"
1154
- version = "2.54.0"
1154
+ version = "2.56.0"
1155
1155
  dependencies = [
1156
1156
  "annotate-snippets",
1157
1157
  "assert_cmd",
@@ -1194,7 +1194,7 @@ dependencies = [
1194
1194
 
1195
1195
  [[package]]
1196
1196
  name = "panache-formatter"
1197
- version = "0.12.0"
1197
+ version = "0.14.0"
1198
1198
  dependencies = [
1199
1199
  "insta",
1200
1200
  "log",
@@ -1202,6 +1202,9 @@ dependencies = [
1202
1202
  "pretty_yaml",
1203
1203
  "pulldown-latex",
1204
1204
  "rowan",
1205
+ "schemars",
1206
+ "serde",
1207
+ "serde_json",
1205
1208
  "similar-asserts",
1206
1209
  "toml",
1207
1210
  "unicode-width",
@@ -1209,7 +1212,7 @@ dependencies = [
1209
1212
 
1210
1213
  [[package]]
1211
1214
  name = "panache-parser"
1212
- version = "0.17.0"
1215
+ version = "0.17.2"
1213
1216
  dependencies = [
1214
1217
  "entities",
1215
1218
  "insta",
@@ -1782,9 +1785,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
1782
1785
 
1783
1786
  [[package]]
1784
1787
  name = "syn"
1785
- version = "2.0.117"
1788
+ version = "2.0.118"
1786
1789
  source = "registry+https://github.com/rust-lang/crates.io-index"
1787
- checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
1790
+ checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
1788
1791
  dependencies = [
1789
1792
  "proc-macro2",
1790
1793
  "quote",
@@ -2132,9 +2135,9 @@ dependencies = [
2132
2135
 
2133
2136
  [[package]]
2134
2137
  name = "which"
2135
- version = "8.0.3"
2138
+ version = "8.0.4"
2136
2139
  source = "registry+https://github.com/rust-lang/crates.io-index"
2137
- checksum = "c789537cf2f7f55be8e6192f92e464174ee55f91af622777f7f1ceb0dbccd03e"
2140
+ checksum = "48d7cd18d4acb58fb3cdfe9ea54e6cd96a4e7d4cc45c56338b236e82dad47248"
2138
2141
  dependencies = [
2139
2142
  "libc",
2140
2143
  ]
@@ -7,7 +7,7 @@ authors = ["Johan Larsson <johan@jolars.co>"]
7
7
 
8
8
  [package]
9
9
  name = "panache"
10
- version = "2.54.0"
10
+ version = "2.56.0"
11
11
  edition.workspace = true
12
12
  readme = "README.md"
13
13
  description = "An LSP, formatter, and linter for Markdown, Quarto, and R Markdown"
@@ -31,14 +31,6 @@ authors.workspace = true
31
31
 
32
32
  [workspace]
33
33
  members = ["crates/panache-parser", "crates/panache-formatter"]
34
- # Excluded because this crate must be compiled to wasm32-unknown-unknown to work
35
- # (it relies on `dprint_core::generate_plugin_code!`, which is only defined on
36
- # that target). Build with:
37
- # cargo build --manifest-path crates/panache-dprint/Cargo.toml \
38
- # --release --target wasm32-unknown-unknown
39
- exclude = [
40
- "crates/panache-dprint",
41
- ]
42
34
 
43
35
  [lib]
44
36
  doctest = false
@@ -49,8 +41,8 @@ path = "src/main.rs"
49
41
  required-features = ["cli"]
50
42
 
51
43
  [dependencies]
52
- panache-formatter = { path = "crates/panache-formatter", version = "0.12.0" }
53
- panache-parser = { path = "crates/panache-parser", version = "0.17.0", features = [
44
+ panache-formatter = { path = "crates/panache-formatter", version = "0.14.0" }
45
+ panache-parser = { path = "crates/panache-parser", version = "0.17.2", features = [
54
46
  "serde",
55
47
  "schema",
56
48
  ] }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: panache-cli
3
- Version: 2.54.0
3
+ Version: 2.56.0
4
4
  Classifier: Development Status :: 5 - Production/Stable
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -1,5 +1,33 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.14.0](https://github.com/jolars/panache/compare/panache-formatter-v0.13.0...panache-formatter-v0.14.0) (2026-06-17)
4
+
5
+ ### Features
6
+ - **formatter:** expose config-enum JsonSchema behind schema feature ([`5062bb5`](https://github.com/jolars/panache/commit/5062bb52db346572748752210e2c6ec22b97e37d))
7
+ - **formatter:** add `table-indent` config option ([`1365b80`](https://github.com/jolars/panache/commit/1365b801c48fbb8670ff8343884b20e5b427f1c7)), resolves [#344](https://github.com/jolars/panache/issues/344) and [#352](https://github.com/jolars/panache/issues/352)
8
+ - **formatter:** hang math binary continuations flush under the RHS ([`0fae430`](https://github.com/jolars/panache/commit/0fae4303b8a758a7ac3a218170dfc9fb7a0c4409))
9
+ - **formatter:** align assignment-led math chains under the RHS ([`e20d0d6`](https://github.com/jolars/panache/commit/e20d0d6c36b4fa7bae295ea41ddc27d770fa4755))
10
+
11
+ ### Bug Fixes
12
+ - **formatter:** collapse line breaks inside split citations ([`148f69f`](https://github.com/jolars/panache/commit/148f69fb2d97ba5c42eb0b92645163cdc7ee4602))
13
+
14
+ ### Dependencies
15
+ - updated crates/panache-parser to v0.17.2
16
+
17
+ ## [0.13.0](https://github.com/jolars/panache/compare/panache-formatter-v0.12.0...panache-formatter-v0.13.0) (2026-06-15)
18
+
19
+ ### Features
20
+ - **formatter:** nest broken binary math continuations by `math-indent` ([`5948ca1`](https://github.com/jolars/panache/commit/5948ca15bb1fa1350e91dbf8fdfc5e11f0e40c32))
21
+ - **formatter:** default `math-indent` to 2 ([`3d0422b`](https://github.com/jolars/panache/commit/3d0422b8355e57b2d9e04b0ac86128da414b75b2))
22
+
23
+ ### Bug Fixes
24
+ - **formatter:** fix(formatter): charge math-indent against display line-break budget ([`754faaa`](https://github.com/jolars/panache/commit/754faaa451ae418a681237f86bc5ad3d6096c92f))
25
+ - **parser:** claim trailing caption for table-first list item ([`a09f066`](https://github.com/jolars/panache/commit/a09f066a9493f3f626b44691023c59c151caafb8))
26
+ - **formatter:** re-emit list marker for table-first item ([`9633b86`](https://github.com/jolars/panache/commit/9633b8632a2f075df3d59852cf414933c9aaba44))
27
+
28
+ ### Dependencies
29
+ - updated crates/panache-parser to v0.17.1
30
+
3
31
  ## [0.12.0](https://github.com/jolars/panache/compare/panache-formatter-v0.11.0...panache-formatter-v0.12.0) (2026-06-13)
4
32
 
5
33
  ### Features
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "panache-formatter"
3
- version = "0.12.0"
3
+ version = "0.14.0"
4
4
  edition.workspace = true
5
5
  include = [
6
6
  "/src/**/*",
@@ -18,12 +18,20 @@ keywords = ["quarto", "pandoc", "markdown", "formatter"]
18
18
  categories = ["text-processing"]
19
19
 
20
20
  [dependencies]
21
- panache-parser = { path = "../panache-parser", version = "0.17.0" }
21
+ panache-parser = { path = "../panache-parser", version = "0.17.2" }
22
22
  log = { version = "0.4.31", features = ["release_max_level_debug"] }
23
23
  rowan = "0.16.1"
24
+ serde = { version = "1.0", features = ["derive"], optional = true }
25
+ schemars = { version = "1.0", optional = true }
24
26
  unicode-width = "0.2"
25
27
 
28
+ [features]
29
+ default = []
30
+ serde = ["dep:serde", "panache-parser/serde"]
31
+ schema = ["serde", "dep:schemars", "panache-parser/schema"]
32
+
26
33
  [dev-dependencies]
34
+ serde_json = "1.0"
27
35
  insta = { version = "1.47.2", features = ["json"] }
28
36
  # TEMPORARY: cross-validation oracle only (tests/yaml_cross_validation.rs).
29
37
  # The in-tree formatter is the source of truth. Drop this dep (and re-base
@@ -15,6 +15,9 @@ fn default_external_max_parallel() -> usize {
15
15
  }
16
16
 
17
17
  #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
18
+ #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19
+ #[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
20
+ #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
18
21
  pub enum MathDelimiterStyle {
19
22
  /// Preserve original delimiter style (\(...\) stays \(...\), $...$ stays $...$)
20
23
  #[default]
@@ -25,7 +28,13 @@ pub enum MathDelimiterStyle {
25
28
  Backslash,
26
29
  }
27
30
 
31
+ /// Default indentation (in columns) for top-level tables.
32
+ pub const DEFAULT_TABLE_INDENT: usize = 2;
33
+
28
34
  #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
35
+ #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
36
+ #[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
37
+ #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
29
38
  pub enum TabStopMode {
30
39
  /// Normalize tabs to spaces (4-column tab stop).
31
40
  #[default]
@@ -43,6 +52,9 @@ pub struct FormatterConfig {
43
52
  }
44
53
 
45
54
  #[derive(Debug, Clone, PartialEq)]
55
+ #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
56
+ #[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
57
+ #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
46
58
  pub enum WrapMode {
47
59
  Preserve,
48
60
  Reflow,
@@ -53,6 +65,9 @@ pub enum WrapMode {
53
65
  }
54
66
 
55
67
  #[derive(Debug, Clone, PartialEq)]
68
+ #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
69
+ #[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
70
+ #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
56
71
  pub enum LineEnding {
57
72
  Auto,
58
73
  Lf,
@@ -60,6 +75,9 @@ pub enum LineEnding {
60
75
  }
61
76
 
62
77
  #[derive(Debug, Clone, PartialEq)]
78
+ #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
79
+ #[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
80
+ #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
63
81
  pub enum BlankLines {
64
82
  /// Preserve original blank lines (any number)
65
83
  Preserve,
@@ -166,6 +184,11 @@ pub struct Config {
166
184
  pub line_width: usize,
167
185
  pub math_indent: usize,
168
186
  pub math_delimiter_style: MathDelimiterStyle,
187
+ /// Indentation (in columns) applied to top-level pipe, simple, and
188
+ /// multiline tables. Grid tables ignore this and stay flush at column 0,
189
+ /// since Pandoc only recognizes a grid table whose border starts at column
190
+ /// 0. Nested tables honor their container indent instead.
191
+ pub table_indent: usize,
169
192
  pub tab_stops: TabStopMode,
170
193
  pub tab_width: usize,
171
194
  pub wrap: Option<WrapMode>,
@@ -200,8 +223,9 @@ impl Default for Config {
200
223
  formatter_extensions: FormatterExtensions::for_flavor(flavor),
201
224
  line_ending: Some(LineEnding::Auto),
202
225
  line_width: 80,
203
- math_indent: 0,
226
+ math_indent: 2,
204
227
  math_delimiter_style: MathDelimiterStyle::default(),
228
+ table_indent: DEFAULT_TABLE_INDENT,
205
229
  tab_stops: TabStopMode::Normalize,
206
230
  tab_width: 4,
207
231
  wrap: Some(WrapMode::Reflow),
@@ -249,6 +273,11 @@ impl ConfigBuilder {
249
273
  self
250
274
  }
251
275
 
276
+ pub fn table_indent(mut self, indent: usize) -> Self {
277
+ self.config.table_indent = indent;
278
+ self
279
+ }
280
+
252
281
  pub fn tab_width(mut self, width: usize) -> Self {
253
282
  self.config.tab_width = width;
254
283
  self
@@ -273,3 +302,49 @@ impl ConfigBuilder {
273
302
  self.config
274
303
  }
275
304
  }
305
+
306
+ #[cfg(all(test, feature = "schema"))]
307
+ mod schema_tests {
308
+ use super::*;
309
+
310
+ /// Assert the emitted JSON Schema exposes exactly the expected lowercase
311
+ /// wire values (and no PascalCase variant names). Substring checks keep this
312
+ /// robust to schemars emitting a flat `enum` array vs. a `oneOf`-of-`const`
313
+ /// shape — the doc comments on some variants become per-value descriptions.
314
+ fn assert_wire_values<T: schemars::JsonSchema>(expected: &[&str]) {
315
+ let s = serde_json::to_string(&schemars::schema_for!(T)).unwrap();
316
+ for value in expected {
317
+ assert!(
318
+ s.contains(&format!("\"{value}\"")),
319
+ "expected lowercase wire value {value:?} in schema: {s}"
320
+ );
321
+ }
322
+ }
323
+
324
+ #[test]
325
+ fn math_delimiter_style_values_are_lowercase() {
326
+ assert_wire_values::<MathDelimiterStyle>(&["preserve", "dollars", "backslash"]);
327
+ }
328
+
329
+ #[test]
330
+ fn tab_stop_mode_values_are_lowercase() {
331
+ assert_wire_values::<TabStopMode>(&["normalize", "preserve"]);
332
+ }
333
+
334
+ #[test]
335
+ fn wrap_mode_values_are_lowercase() {
336
+ assert_wire_values::<WrapMode>(&["preserve", "reflow", "sentence", "semantic"]);
337
+ let s = serde_json::to_string(&schemars::schema_for!(WrapMode)).unwrap();
338
+ assert!(!s.contains("\"Reflow\""), "PascalCase variant leaked: {s}");
339
+ }
340
+
341
+ #[test]
342
+ fn line_ending_values_are_lowercase() {
343
+ assert_wire_values::<LineEnding>(&["auto", "lf", "crlf"]);
344
+ }
345
+
346
+ #[test]
347
+ fn blank_lines_values_are_lowercase() {
348
+ assert_wire_values::<BlankLines>(&["preserve", "collapse"]);
349
+ }
350
+ }
@@ -33,6 +33,85 @@ fn expand_tabs_code_span(text: &str, tab_width: usize) -> String {
33
33
  out.trim().to_string()
34
34
  }
35
35
 
36
+ /// Render a `CITATION` or `CROSSREF` node by concatenating its child tokens.
37
+ ///
38
+ /// Both kinds share the same syntax (`[ ... @key ... ]`) and are emitted the
39
+ /// same way: smart-normalize text tokens, skip the whitespace that follows a
40
+ /// blockquote marker, then collapse any internal line break (a citation may be
41
+ /// split across input lines) so the unit reflows like ordinary inline text
42
+ /// instead of pinning a hard newline into the paragraph.
43
+ fn format_citation_like(node: &SyntaxNode, config: &Config) -> String {
44
+ let mut result = String::new();
45
+ let mut skip_marker_whitespace = false;
46
+ for child in node.children_with_tokens() {
47
+ match child {
48
+ NodeOrToken::Token(tok) if tok.kind() == SyntaxKind::BLOCK_QUOTE_MARKER => {
49
+ skip_marker_whitespace = true;
50
+ }
51
+ NodeOrToken::Token(tok)
52
+ if tok.kind() == SyntaxKind::WHITESPACE && skip_marker_whitespace =>
53
+ {
54
+ skip_marker_whitespace = false;
55
+ }
56
+ NodeOrToken::Token(tok) => {
57
+ skip_marker_whitespace = false;
58
+ result.push_str(
59
+ normalize_smart_punctuation(
60
+ tok.text(),
61
+ config.formatter_extensions.smart,
62
+ config.formatter_extensions.smart_quotes,
63
+ )
64
+ .as_ref(),
65
+ );
66
+ }
67
+ NodeOrToken::Node(n) => {
68
+ skip_marker_whitespace = false;
69
+ result.push_str(&n.text().to_string());
70
+ }
71
+ }
72
+ }
73
+ collapse_internal_newlines(&result).into_owned()
74
+ }
75
+
76
+ /// Collapse any whitespace run that contains a line break into a single space.
77
+ ///
78
+ /// A citation or cross-reference split across input lines leaves a literal
79
+ /// newline inside the assembled string. Emitting it verbatim makes the
80
+ /// surrounding paragraph un-reflowable, so we normalize it the way the wrapper
81
+ /// treats ordinary inter-word whitespace.
82
+ fn collapse_internal_newlines(text: &str) -> std::borrow::Cow<'_, str> {
83
+ if !text.contains('\n') {
84
+ return std::borrow::Cow::Borrowed(text);
85
+ }
86
+ let mut out = String::with_capacity(text.len());
87
+ let mut chars = text.chars().peekable();
88
+ while let Some(ch) = chars.next() {
89
+ if ch.is_whitespace() {
90
+ // Consume the whole whitespace run, tracking whether it contains a
91
+ // line break.
92
+ let mut has_newline = ch == '\n';
93
+ let mut run = String::from(ch);
94
+ while let Some(&next) = chars.peek() {
95
+ if next.is_whitespace() {
96
+ has_newline |= next == '\n';
97
+ run.push(next);
98
+ chars.next();
99
+ } else {
100
+ break;
101
+ }
102
+ }
103
+ if has_newline {
104
+ out.push(' ');
105
+ } else {
106
+ out.push_str(&run);
107
+ }
108
+ } else {
109
+ out.push(ch);
110
+ }
111
+ }
112
+ std::borrow::Cow::Owned(out)
113
+ }
114
+
36
115
  /// Format an inline node to normalized string (e.g., emphasis with asterisks)
37
116
  pub(super) fn format_inline_node(node: &SyntaxNode, config: &Config) -> String {
38
117
  match node.kind() {
@@ -536,8 +615,13 @@ pub(super) fn format_inline_node(node: &SyntaxNode, config: &Config) -> String {
536
615
  result.push_str(&math::format_math(&content, &opts));
537
616
  result.push('\n');
538
617
  } else {
539
- // Process content: trim overall, then strip common leading whitespace
540
- let trimmed_content = content.trim();
618
+ // Process content: trim surrounding newlines (NOT leading spaces)
619
+ // and trailing whitespace, strip common leading whitespace, then
620
+ // re-indent every line by `math_indent`. Trimming only leading
621
+ // newlines keeps each line's true indent visible to `min_indent`,
622
+ // so the re-indent is idempotent: a later pass strips the pad as
623
+ // common indentation before re-applying it, rather than stacking.
624
+ let trimmed_content = content.trim_start_matches(['\n', '\r']).trim_end();
541
625
  if !trimmed_content.is_empty() {
542
626
  // Find minimum indentation across all non-empty lines
543
627
  let min_indent = trimmed_content
@@ -547,12 +631,18 @@ pub(super) fn format_inline_node(node: &SyntaxNode, config: &Config) -> String {
547
631
  .min()
548
632
  .unwrap_or(0);
549
633
 
550
- // Strip common indentation from each line
634
+ let pad = " ".repeat(config.math_indent);
635
+ // Strip common indentation, then re-indent each line.
551
636
  for line in trimmed_content.lines() {
552
- if line.len() >= min_indent {
553
- result.push_str(&line[min_indent..]);
637
+ let stripped = if line.len() >= min_indent {
638
+ &line[min_indent..]
554
639
  } else {
555
- result.push_str(line);
640
+ line
641
+ };
642
+ // Skip padding blank lines to avoid trailing whitespace.
643
+ if !stripped.is_empty() {
644
+ result.push_str(&pad);
645
+ result.push_str(stripped);
556
646
  }
557
647
  result.push('\n');
558
648
  }
@@ -604,70 +694,7 @@ pub(super) fn format_inline_node(node: &SyntaxNode, config: &Config) -> String {
604
694
  .join(" ");
605
695
  format!("^[{}]", normalized)
606
696
  }
607
- SyntaxKind::CITATION => {
608
- let mut result = String::new();
609
- let mut skip_marker_whitespace = false;
610
- for child in node.children_with_tokens() {
611
- match child {
612
- NodeOrToken::Token(tok) if tok.kind() == SyntaxKind::BLOCK_QUOTE_MARKER => {
613
- skip_marker_whitespace = true;
614
- }
615
- NodeOrToken::Token(tok)
616
- if tok.kind() == SyntaxKind::WHITESPACE && skip_marker_whitespace =>
617
- {
618
- skip_marker_whitespace = false;
619
- }
620
- NodeOrToken::Token(tok) => {
621
- skip_marker_whitespace = false;
622
- result.push_str(
623
- normalize_smart_punctuation(
624
- tok.text(),
625
- config.formatter_extensions.smart,
626
- config.formatter_extensions.smart_quotes,
627
- )
628
- .as_ref(),
629
- );
630
- }
631
- NodeOrToken::Node(n) => {
632
- skip_marker_whitespace = false;
633
- result.push_str(&n.text().to_string());
634
- }
635
- }
636
- }
637
- result
638
- }
639
- SyntaxKind::CROSSREF => {
640
- let mut result = String::new();
641
- let mut skip_marker_whitespace = false;
642
- for child in node.children_with_tokens() {
643
- match child {
644
- NodeOrToken::Token(tok) if tok.kind() == SyntaxKind::BLOCK_QUOTE_MARKER => {
645
- skip_marker_whitespace = true;
646
- }
647
- NodeOrToken::Token(tok)
648
- if tok.kind() == SyntaxKind::WHITESPACE && skip_marker_whitespace =>
649
- {
650
- skip_marker_whitespace = false;
651
- }
652
- NodeOrToken::Token(tok) => {
653
- skip_marker_whitespace = false;
654
- result.push_str(
655
- normalize_smart_punctuation(
656
- tok.text(),
657
- config.formatter_extensions.smart,
658
- config.formatter_extensions.smart_quotes,
659
- )
660
- .as_ref(),
661
- );
662
- }
663
- NodeOrToken::Node(n) => {
664
- skip_marker_whitespace = false;
665
- result.push_str(&n.text().to_string());
666
- }
667
- }
668
- }
669
- result
670
- }
697
+ SyntaxKind::CITATION | SyntaxKind::CROSSREF => format_citation_like(node, config),
671
698
  _ => {
672
699
  // For other inline nodes, just return their text
673
700
  node.text().to_string()
@@ -1,6 +1,7 @@
1
1
  use crate::config::WrapMode;
2
2
  use crate::formatter::indent_utils::{calculate_list_item_indent, is_alignable_marker};
3
3
  use crate::formatter::inline_layout::{self, WrapStrategy};
4
+ use crate::formatter::tables;
4
5
  use crate::syntax::{AstNode, BlockQuote, FencedDiv, SyntaxKind, SyntaxNode};
5
6
  use rowan::NodeOrToken;
6
7
 
@@ -1188,6 +1189,80 @@ impl Formatter {
1188
1189
  self.format_node_sync(&child, content_indent);
1189
1190
  }
1190
1191
  }
1192
+ SyntaxKind::PIPE_TABLE | SyntaxKind::GRID_TABLE => {
1193
+ // A table can be a LIST_ITEM's sole/first child (the parser
1194
+ // nests it; e.g. `- | a | b |`). The wrapping pass above
1195
+ // emits nothing for an item with no PLAIN/PARAGRAPH
1196
+ // content_node, so re-emit the marker here — otherwise it is
1197
+ // dropped and the table floats out of the list (and the
1198
+ // ordered-list re-indent breaks idempotency). The first
1199
+ // table line sits on the marker line; a bare marker with the
1200
+ // table indented below would reparse the table as a
1201
+ // paragraph.
1202
+ //
1203
+ // Captioned tables splice too: the parser now nests a
1204
+ // table-first item's trailing `: cap`/`Table: cap` as the
1205
+ // table's `TABLE_CAPTION` (matching pandoc), so the whole
1206
+ // table — caption rendered below by `format_pipe_table` /
1207
+ // `format_grid_table` at `content_indent` — goes on the
1208
+ // marker line. The splice strips only the first line's
1209
+ // indent, so the caption keeps its indentation.
1210
+ let no_content_emitted = lines.is_empty()
1211
+ && preserve_lines.is_none()
1212
+ && sentence_lines.is_none()
1213
+ && content_node.is_none()
1214
+ && !has_only_empty_nested_list;
1215
+ let prev_kind = child.prev_sibling().map(|s| s.kind());
1216
+ let is_first_real_child = !matches!(
1217
+ prev_kind,
1218
+ Some(SyntaxKind::PLAIN)
1219
+ | Some(SyntaxKind::PARAGRAPH)
1220
+ | Some(SyntaxKind::HEADING)
1221
+ | Some(SyntaxKind::CODE_BLOCK)
1222
+ | Some(SyntaxKind::BLOCK_QUOTE)
1223
+ | Some(SyntaxKind::LIST)
1224
+ | Some(SyntaxKind::HORIZONTAL_RULE)
1225
+ | Some(SyntaxKind::HTML_BLOCK)
1226
+ | Some(SyntaxKind::HTML_BLOCK_DIV)
1227
+ | Some(SyntaxKind::PIPE_TABLE)
1228
+ | Some(SyntaxKind::GRID_TABLE)
1229
+ );
1230
+ let content_indent = list_indent.hanging_indent(total_indent);
1231
+ // The marker prefix occupies exactly `content_indent`
1232
+ // columns — except under `four_space_rule` (a flat tab
1233
+ // stop) or a task checkbox (which widens the marker line);
1234
+ // in those cases the splice would misalign, so fall back.
1235
+ let prefix_width = total_indent
1236
+ + list_indent.marker_padding
1237
+ + marker.len()
1238
+ + list_indent.spaces_after;
1239
+ if no_content_emitted
1240
+ && is_first_real_child
1241
+ && checkbox.is_none()
1242
+ && prefix_width == content_indent
1243
+ {
1244
+ // First table line on the marker line. Both `prefix` and
1245
+ // the table's first line are exactly `content_indent`
1246
+ // ASCII spaces wide, so splicing is byte-safe.
1247
+ let prefix = format!(
1248
+ "{}{}{}{}",
1249
+ " ".repeat(total_indent),
1250
+ " ".repeat(list_indent.marker_padding),
1251
+ marker,
1252
+ " ".repeat(list_indent.spaces_after),
1253
+ );
1254
+ let table_str = match child.kind() {
1255
+ SyntaxKind::PIPE_TABLE => {
1256
+ tables::format_pipe_table(&child, &self.config, content_indent)
1257
+ }
1258
+ _ => tables::format_grid_table(&child, &self.config, content_indent),
1259
+ };
1260
+ self.output.push_str(&prefix);
1261
+ self.output.push_str(&table_str[content_indent..]);
1262
+ } else {
1263
+ self.format_node_sync(&child, content_indent);
1264
+ }
1265
+ }
1191
1266
  _ => {
1192
1267
  // Other block elements - format with proper indentation
1193
1268
  let content_indent = list_indent.hanging_indent(total_indent);