panache-cli 2.55.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.55.0 → panache_cli-2.56.0}/Cargo.lock +10 -7
  2. {panache_cli-2.55.0 → panache_cli-2.56.0}/Cargo.toml +3 -11
  3. {panache_cli-2.55.0 → panache_cli-2.56.0}/PKG-INFO +1 -1
  4. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/CHANGELOG.md +14 -0
  5. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/Cargo.toml +10 -2
  6. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/config.rs +75 -0
  7. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/inline.rs +80 -64
  8. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/math/STYLE.md +48 -13
  9. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/math/linebreak.rs +159 -100
  10. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/math/operators.rs +1 -1
  11. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/math/render.rs +59 -22
  12. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/math.rs +4 -3
  13. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/tables.rs +11 -7
  14. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/CHANGELOG.md +5 -0
  15. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/Cargo.toml +1 -1
  16. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/pandoc_ast.rs +38 -1
  17. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/block_dispatcher.rs +20 -0
  18. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/code_blocks.rs +14 -32
  19. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tables.rs +61 -0
  20. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/attributes.rs +84 -0
  21. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/config/types.rs +39 -0
  22. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/config.rs +33 -0
  23. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/formatter.rs +1 -0
  24. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/main.rs +39 -3
  25. {panache_cli-2.55.0 → panache_cli-2.56.0}/LICENSE +0 -0
  26. {panache_cli-2.55.0 → panache_cli-2.56.0}/README.md +0 -0
  27. {panache_cli-2.55.0 → panache_cli-2.56.0}/build.rs +0 -0
  28. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/README.md +0 -0
  29. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/directives.rs +0 -0
  30. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/blockquotes.rs +0 -0
  31. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/code_blocks.rs +0 -0
  32. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/core.rs +0 -0
  33. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/fenced_divs.rs +0 -0
  34. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/hashpipe.rs +0 -0
  35. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/headings.rs +0 -0
  36. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/indent_utils.rs +0 -0
  37. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/inline_layout.rs +0 -0
  38. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/lists.rs +0 -0
  39. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/metadata.rs +0 -0
  40. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/paragraphs.rs +0 -0
  41. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/sentence_wrap.rs +0 -0
  42. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/shortcodes.rs +0 -0
  43. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/smart.rs +0 -0
  44. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/utils.rs +0 -0
  45. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/yaml/STYLE.md +0 -0
  46. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/yaml/block_map.rs +0 -0
  47. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/yaml/block_sequence.rs +0 -0
  48. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/yaml/document.rs +0 -0
  49. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/yaml/flow.rs +0 -0
  50. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/yaml/options.rs +0 -0
  51. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/yaml/scalar.rs +0 -0
  52. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter/yaml.rs +0 -0
  53. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/formatter.rs +0 -0
  54. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/lib.rs +0 -0
  55. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/parser.rs +0 -0
  56. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/syntax.rs +0 -0
  57. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/utils.rs +0 -0
  58. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-formatter/src/yaml_engine.rs +0 -0
  59. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/README.md +0 -0
  60. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/build.rs +0 -0
  61. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/lib.rs +0 -0
  62. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/options.rs +0 -0
  63. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/blockquotes.rs +0 -0
  64. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/container_prefix.rs +0 -0
  65. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/definition_lists.rs +0 -0
  66. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/fenced_divs.rs +0 -0
  67. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/figures.rs +0 -0
  68. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/headings.rs +0 -0
  69. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/horizontal_rules.rs +0 -0
  70. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/html_blocks.rs +0 -0
  71. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/indented_code.rs +0 -0
  72. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/latex_envs.rs +0 -0
  73. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/line_blocks.rs +0 -0
  74. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/lists.rs +0 -0
  75. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/metadata.rs +0 -0
  76. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/paragraphs.rs +0 -0
  77. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/raw_blocks.rs +0 -0
  78. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/reference_links.rs +0 -0
  79. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tests/blanklines.rs +0 -0
  80. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tests/blockquotes.rs +0 -0
  81. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tests/code_blocks.rs +0 -0
  82. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tests/definition_lists.rs +0 -0
  83. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tests/headings.rs +0 -0
  84. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tests/helpers.rs +0 -0
  85. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tests/lists.rs +0 -0
  86. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tests/losslessness.rs +0 -0
  87. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks/tests/metadata_guards.rs +0 -0
  88. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/blocks.rs +0 -0
  89. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/core.rs +0 -0
  90. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/diagnostics.rs +0 -0
  91. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/bookdown.rs +0 -0
  92. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/bracketed_spans.rs +0 -0
  93. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/citations.rs +0 -0
  94. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/code_spans.rs +0 -0
  95. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/core.rs +0 -0
  96. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/emoji.rs +0 -0
  97. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/escapes.rs +0 -0
  98. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/inline_executable.rs +0 -0
  99. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/inline_footnotes.rs +0 -0
  100. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/inline_html.rs +0 -0
  101. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/inline_ir.rs +0 -0
  102. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/latex.rs +0 -0
  103. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/links.rs +0 -0
  104. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/mark.rs +0 -0
  105. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/math.rs +0 -0
  106. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/native_spans.rs +0 -0
  107. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/raw_inline.rs +0 -0
  108. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/refdef_map.rs +0 -0
  109. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/shortcodes.rs +0 -0
  110. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/sink.rs +0 -0
  111. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/strikeout.rs +0 -0
  112. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/subscript.rs +0 -0
  113. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/superscript.rs +0 -0
  114. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/tests.rs +0 -0
  115. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/uri-schemes.csv +0 -0
  116. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines/wikilinks.rs +0 -0
  117. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/inlines.rs +0 -0
  118. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/math.rs +0 -0
  119. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/chunk_options.rs +0 -0
  120. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/container_stack.rs +0 -0
  121. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/continuation.rs +0 -0
  122. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/helpers.rs +0 -0
  123. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/inline_emission.rs +0 -0
  124. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/list_item_buffer.rs +0 -0
  125. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/marker_utils.rs +0 -0
  126. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/text_buffer.rs +0 -0
  127. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/tree_copy.rs +0 -0
  128. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils/yaml_regions.rs +0 -0
  129. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/utils.rs +0 -0
  130. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/yaml/cooking.rs +0 -0
  131. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/yaml/events.rs +0 -0
  132. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/yaml/model.rs +0 -0
  133. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/yaml/parser.rs +0 -0
  134. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/yaml/profile.rs +0 -0
  135. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/yaml/scanner.rs +0 -0
  136. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/yaml/validator.rs +0 -0
  137. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser/yaml.rs +0 -0
  138. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/parser.rs +0 -0
  139. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/range_utils.rs +0 -0
  140. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/alerts.rs +0 -0
  141. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/ast.rs +0 -0
  142. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/attributes.rs +0 -0
  143. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/block_quotes.rs +0 -0
  144. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/blocks.rs +0 -0
  145. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/chunk_options.rs +0 -0
  146. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/citations.rs +0 -0
  147. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/code_blocks.rs +0 -0
  148. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/crossrefs.rs +0 -0
  149. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/definitions.rs +0 -0
  150. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/fenced_divs.rs +0 -0
  151. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/headings.rs +0 -0
  152. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/inlines.rs +0 -0
  153. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/kind.rs +0 -0
  154. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/links.rs +0 -0
  155. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/lists.rs +0 -0
  156. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/math.rs +0 -0
  157. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/raw_tex.rs +0 -0
  158. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/references.rs +0 -0
  159. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/shortcodes.rs +0 -0
  160. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/tables.rs +0 -0
  161. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/yaml.rs +0 -0
  162. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax/yaml_ast.rs +0 -0
  163. {panache_cli-2.55.0 → panache_cli-2.56.0}/crates/panache-parser/src/syntax.rs +0 -0
  164. {panache_cli-2.55.0 → panache_cli-2.56.0}/pyproject.toml +0 -0
  165. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/bib/bibtex.rs +0 -0
  166. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/bib/csl_json.rs +0 -0
  167. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/bib/csl_yaml.rs +0 -0
  168. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/bib/index.rs +0 -0
  169. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/bib/ris.rs +0 -0
  170. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/bib.rs +0 -0
  171. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/cache.rs +0 -0
  172. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/cli.rs +0 -0
  173. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/config/formatter_presets.rs +0 -0
  174. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/config/types/schema_helpers.rs +0 -0
  175. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/diagnostic_renderer.rs +0 -0
  176. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/directives.rs +0 -0
  177. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/external_formatters_common.rs +0 -0
  178. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/external_formatters_sync.rs +0 -0
  179. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/external_tools_common.rs +0 -0
  180. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/includes.rs +0 -0
  181. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lib.rs +0 -0
  182. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/code_block_collector.rs +0 -0
  183. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/diagnostics.rs +0 -0
  184. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/external_linters/clippy.rs +0 -0
  185. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/external_linters/eslint.rs +0 -0
  186. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/external_linters/jarl.rs +0 -0
  187. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/external_linters/ruff.rs +0 -0
  188. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/external_linters/shellcheck.rs +0 -0
  189. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/external_linters/staticcheck.rs +0 -0
  190. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/external_linters.rs +0 -0
  191. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/external_linters_sync.rs +0 -0
  192. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/index.rs +0 -0
  193. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/metadata_diagnostics.rs +0 -0
  194. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/offsets.rs +0 -0
  195. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/adjacent_footnote_refs.rs +0 -0
  196. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/chunk_label_spaces.rs +0 -0
  197. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/citation_keys.rs +0 -0
  198. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/crossref_as_link_target.rs +0 -0
  199. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/duplicate_references.rs +0 -0
  200. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/emoji_aliases.rs +0 -0
  201. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/empty_list_item.rs +0 -0
  202. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/figure_crossref_captions.rs +0 -0
  203. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/footnote_ref_in_footnote_def.rs +0 -0
  204. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/heading_eaten_attrs.rs +0 -0
  205. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/heading_hierarchy.rs +0 -0
  206. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/heading_strip_comments_residue.rs +0 -0
  207. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/html_entities.rs +0 -0
  208. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/link_text_is_url.rs +0 -0
  209. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/math_content.rs +0 -0
  210. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/missing_chunk_labels.rs +0 -0
  211. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/stray_fenced_div_markers.rs +0 -0
  212. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/undefined_anchor.rs +0 -0
  213. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/undefined_references.rs +0 -0
  214. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules/unused_definitions.rs +0 -0
  215. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/rules.rs +0 -0
  216. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter/runner.rs +0 -0
  217. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/linter.rs +0 -0
  218. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/config.rs +0 -0
  219. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/context.rs +0 -0
  220. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/conversions.rs +0 -0
  221. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/dispatch.rs +0 -0
  222. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/documents.rs +0 -0
  223. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/global_state.rs +0 -0
  224. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/code_actions.rs +0 -0
  225. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/completion.rs +0 -0
  226. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/diagnostics.rs +0 -0
  227. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/document_links.rs +0 -0
  228. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/document_symbols.rs +0 -0
  229. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/file_rename.rs +0 -0
  230. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/file_watcher.rs +0 -0
  231. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/folding_ranges.rs +0 -0
  232. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/footnote_conversion.rs +0 -0
  233. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/formatting.rs +0 -0
  234. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/goto_definition.rs +0 -0
  235. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/heading_link_conversion.rs +0 -0
  236. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/hover.rs +0 -0
  237. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/link_conversion.rs +0 -0
  238. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/list_conversion.rs +0 -0
  239. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/prepare_rename.rs +0 -0
  240. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/references.rs +0 -0
  241. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/rename.rs +0 -0
  242. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/shortcode_args.rs +0 -0
  243. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers/workspace_symbols.rs +0 -0
  244. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/handlers.rs +0 -0
  245. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/helpers.rs +0 -0
  246. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/navigation.rs +0 -0
  247. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/symbols.rs +0 -0
  248. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/task_pool.rs +0 -0
  249. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/testing.rs +0 -0
  250. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp/uri_ext.rs +0 -0
  251. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/lsp.rs +0 -0
  252. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/metadata/bibliography.rs +0 -0
  253. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/metadata/citations.rs +0 -0
  254. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/metadata/project.rs +0 -0
  255. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/metadata/references.rs +0 -0
  256. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/metadata/yaml.rs +0 -0
  257. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/metadata.rs +0 -0
  258. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/parser.rs +0 -0
  259. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/range_utils.rs +0 -0
  260. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/salsa.rs +0 -0
  261. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/syntax.rs +0 -0
  262. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/utils.rs +0 -0
  263. {panache_cli-2.55.0 → panache_cli-2.56.0}/src/yaml_engine.rs +0 -0
  264. {panache_cli-2.55.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.55.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.13.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.1"
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.55.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.13.0" }
53
- panache-parser = { path = "crates/panache-parser", version = "0.17.1", 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.55.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,19 @@
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
+
3
17
  ## [0.13.0](https://github.com/jolars/panache/compare/panache-formatter-v0.12.0...panache-formatter-v0.13.0) (2026-06-15)
4
18
 
5
19
  ### Features
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "panache-formatter"
3
- version = "0.13.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.1" }
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>,
@@ -202,6 +225,7 @@ impl Default for Config {
202
225
  line_width: 80,
203
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() {
@@ -615,70 +694,7 @@ pub(super) fn format_inline_node(node: &SyntaxNode, config: &Config) -> String {
615
694
  .join(" ");
616
695
  format!("^[{}]", normalized)
617
696
  }
618
- SyntaxKind::CITATION => {
619
- let mut result = String::new();
620
- let mut skip_marker_whitespace = false;
621
- for child in node.children_with_tokens() {
622
- match child {
623
- NodeOrToken::Token(tok) if tok.kind() == SyntaxKind::BLOCK_QUOTE_MARKER => {
624
- skip_marker_whitespace = true;
625
- }
626
- NodeOrToken::Token(tok)
627
- if tok.kind() == SyntaxKind::WHITESPACE && skip_marker_whitespace =>
628
- {
629
- skip_marker_whitespace = false;
630
- }
631
- NodeOrToken::Token(tok) => {
632
- skip_marker_whitespace = false;
633
- result.push_str(
634
- normalize_smart_punctuation(
635
- tok.text(),
636
- config.formatter_extensions.smart,
637
- config.formatter_extensions.smart_quotes,
638
- )
639
- .as_ref(),
640
- );
641
- }
642
- NodeOrToken::Node(n) => {
643
- skip_marker_whitespace = false;
644
- result.push_str(&n.text().to_string());
645
- }
646
- }
647
- }
648
- result
649
- }
650
- SyntaxKind::CROSSREF => {
651
- let mut result = String::new();
652
- let mut skip_marker_whitespace = false;
653
- for child in node.children_with_tokens() {
654
- match child {
655
- NodeOrToken::Token(tok) if tok.kind() == SyntaxKind::BLOCK_QUOTE_MARKER => {
656
- skip_marker_whitespace = true;
657
- }
658
- NodeOrToken::Token(tok)
659
- if tok.kind() == SyntaxKind::WHITESPACE && skip_marker_whitespace =>
660
- {
661
- skip_marker_whitespace = false;
662
- }
663
- NodeOrToken::Token(tok) => {
664
- skip_marker_whitespace = false;
665
- result.push_str(
666
- normalize_smart_punctuation(
667
- tok.text(),
668
- config.formatter_extensions.smart,
669
- config.formatter_extensions.smart_quotes,
670
- )
671
- .as_ref(),
672
- );
673
- }
674
- NodeOrToken::Node(n) => {
675
- skip_marker_whitespace = false;
676
- result.push_str(&n.text().to_string());
677
- }
678
- }
679
- }
680
- result
681
- }
697
+ SyntaxKind::CITATION | SyntaxKind::CROSSREF => format_citation_like(node, config),
682
698
  _ => {
683
699
  // For other inline nodes, just return their text
684
700
  node.text().to_string()
@@ -101,14 +101,16 @@ Returned unchanged, never reflowed:
101
101
  wider than `line-width` is broken at its **top-level** operators in a
102
102
  two-level hierarchy keyed on `operators::break_priority` (**relations** >
103
103
  **binary** > everything else). The first relation stays on the opening line;
104
- every later relation starts a continuation **aligned under the first
105
- relation's column**. Then any relation segment that is still over-width
106
- splits before each top-level **binary** operator, with each `+ term` nested
107
- one indent step (2 spaces) deeper, under the relation's right-hand side. The
108
- width budget charges the flat `math-indent` against `line-width`, so a broken
109
- line plus its leading indent still stays within `line-width`. It is
110
- source-cosmetic only --- math ignores whitespace, so the rendered equation is
111
- unchanged:
104
+ every later relation starts a continuation aligned under the **first
105
+ relation** (`linebreak::relation_column`) --- the classic stacked-`=` layout
106
+ for an equality/comparison chain. Then any relation segment that is still
107
+ over-width splits before each top-level **binary** operator, with each
108
+ `+ term` sitting **flush** under that segment's own right-hand side. The
109
+ relation/RHS offset alone supplies the visual nesting; binary continuations
110
+ never pick up an extra step. The width budget charges the flat `math-indent`
111
+ against `line-width`, so a broken line plus its leading indent still stays
112
+ within `line-width`. It is source-cosmetic only --- math ignores whitespace,
113
+ so the rendered equation is unchanged:
112
114
 
113
115
  ```
114
116
  A = aaaaaaaaaa
@@ -120,6 +122,26 @@ Returned unchanged, never reflowed:
120
122
  (At a width where each relation segment fits, no binary breaking happens and
121
123
  only the relation split shows: `A = aaaa + bbbb` / `= cccc + dddd`.)
122
124
 
125
+ **Assignment exception.** When the leading relation is an *assignment* arrow
126
+ (`\gets`, `\leftarrow`, `\mapsto`, `\coloneqq`, or `:=`), the arrow defines
127
+ its LHS rather than equating it, so it is **not** part of the equality chain
128
+ it introduces. The equality continuations then anchor under the assignment's
129
+ *right-hand side* (`linebreak::rhs_start_column`) instead of under the arrow,
130
+ so a wide arrow (`\gets` is 5 cols) does not drag them left. The selector is
131
+ `linebreak::continuation_anchor` / `first_relation_is_assignment`. `\to` and
132
+ `\rightarrow` are intentionally *not* assignments (they are usually limits or
133
+ mappings).
134
+
135
+ ```
136
+ \beta_0 \gets \beta_0 + \frac{4}{n} …
137
+ = \beta_0 - \frac{1}{L_0} …
138
+ = 1/4
139
+ ```
140
+
141
+ This is **fully deterministic**: the layout is a pure function of the
142
+ content, `line-width`, and `math-indent` --- the author's own line breaks and
143
+ indentation are never preserved, only recomputed.
144
+
123
145
  - **Top-level only.** An operator at delimiter depth > 0 --- inside `(…)`,
124
146
  `[…]`, or `\left…\right` (tracked by an open/close counter, since those are
125
147
  *flat token runs*, not nesting nodes), or anywhere inside a `{…}` brace
@@ -138,16 +160,29 @@ Returned unchanged, never reflowed:
138
160
  (Contrast environment-body rows, which keep soft-newline boundaries.) The
139
161
  exception: a soft newline terminating a `%` comment stays a boundary, or
140
162
  the next line is absorbed into the comment.
163
+ - **`\\` relation chains align like an implicit `aligned`.** A genuine hard
164
+ `\\` *does* split logical rows. When ≥ 2 such `\\`-joined rows form a
165
+ relation chain --- the head ends in `\\` and every following row
166
+ `begins_with_top_level_relation` (a continuation like `= b`) --- the
167
+ continuations hang at the head's `continuation_anchor` (under the first
168
+ relation, or the assignment's RHS), exactly as the within-row relation
169
+ breaks do, so a `\\`-broken chain in bare `$$` reads like an `aligned` even
170
+ without one (`relation_chain_alignment`). This fires regardless of width
171
+ (the `\\` are forced breaks). A group containing a top-level `&` is left to
172
+ the existing free-row path (a bare `&` is not a column separator), and `\\`
173
+ rows that are not a relation chain stay flush at the bare `math-indent`.
141
174
  - **Scope:** every over-width free row with a top-level relation **or**
142
175
  binary operator is broken. A **relation chain** (≥ 2 relations) splits at
143
176
  its relations, then nests binary terms inside each over-width segment (as
144
177
  above). A **single-relation** row splits its over-width binary RHS, each
145
- `+ term` nested under the right-hand side. A **standalone binary chain**
146
- (no relation) splits with the first term as the head and each `+ term`
147
- flush under it. The unifying rule: a binary continuation aligns under the
178
+ `+ term` flush under the right-hand side. A **standalone binary chain** (no
179
+ relation) splits with the first term as the head and each `+ term` flush
180
+ under it. The unifying rule: a binary continuation aligns flush under the
148
181
  **first term of its operand sequence** (for a relation segment that is its
149
- RHS; for a bare chain it is the chain itself, so the `+` sits flush). A row
150
- with **no** top-level relation or binary operator (e.g. a single wide
182
+ RHS; for a bare chain it is the chain itself). The relation/RHS offset is
183
+ the only nesting; `math-indent` shifts the whole block but never the
184
+ internal alignment, so the equation's shape is identical at any indent. A
185
+ row with **no** top-level relation or binary operator (e.g. a single wide
151
186
  `\frac{…}{…}`) is left on one over-width line --- like an unbreakable long
152
187
  word in prose reflow. Inline and environment-body math are not line-broken.
153
188