panache-cli 2.54.0__tar.gz → 2.55.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.
- {panache_cli-2.54.0 → panache_cli-2.55.0}/Cargo.lock +3 -3
- {panache_cli-2.54.0 → panache_cli-2.55.0}/Cargo.toml +3 -3
- {panache_cli-2.54.0 → panache_cli-2.55.0}/PKG-INFO +1 -1
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/CHANGELOG.md +14 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/Cargo.toml +2 -2
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/config.rs +1 -1
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/inline.rs +17 -6
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/lists.rs +75 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/math/STYLE.md +5 -3
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/math/linebreak.rs +70 -9
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/math/render.rs +19 -3
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/CHANGELOG.md +5 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/Cargo.toml +1 -1
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/core.rs +130 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/config/types.rs +11 -6
- {panache_cli-2.54.0 → panache_cli-2.55.0}/LICENSE +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/README.md +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/build.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/README.md +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/directives.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/blockquotes.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/code_blocks.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/core.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/fenced_divs.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/hashpipe.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/headings.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/indent_utils.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/inline_layout.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/math/operators.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/math.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/metadata.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/paragraphs.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/sentence_wrap.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/shortcodes.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/smart.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/tables.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/utils.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/yaml/STYLE.md +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/yaml/block_map.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/yaml/block_sequence.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/yaml/document.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/yaml/flow.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/yaml/options.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/yaml/scalar.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/yaml.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/lib.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/parser.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/syntax.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/utils.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/yaml_engine.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/README.md +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/build.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/lib.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/options.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/pandoc_ast.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/block_dispatcher.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/blockquotes.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/code_blocks.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/container_prefix.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/definition_lists.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/fenced_divs.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/figures.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/headings.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/horizontal_rules.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/html_blocks.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/indented_code.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/latex_envs.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/line_blocks.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/lists.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/metadata.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/paragraphs.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/raw_blocks.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/reference_links.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/tables.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/tests/blanklines.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/tests/blockquotes.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/tests/code_blocks.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/tests/definition_lists.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/tests/headings.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/tests/helpers.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/tests/lists.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/tests/losslessness.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks/tests/metadata_guards.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/blocks.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/diagnostics.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/bookdown.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/bracketed_spans.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/citations.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/code_spans.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/core.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/emoji.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/escapes.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/inline_executable.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/inline_footnotes.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/inline_html.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/inline_ir.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/latex.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/links.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/mark.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/math.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/native_spans.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/raw_inline.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/refdef_map.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/shortcodes.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/sink.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/strikeout.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/subscript.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/superscript.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/tests.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/uri-schemes.csv +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines/wikilinks.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/inlines.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/math.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/utils/attributes.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/utils/chunk_options.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/utils/container_stack.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/utils/continuation.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/utils/helpers.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/utils/inline_emission.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/utils/list_item_buffer.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/utils/marker_utils.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/utils/text_buffer.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/utils/tree_copy.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/utils/yaml_regions.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/utils.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/yaml/cooking.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/yaml/events.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/yaml/model.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/yaml/parser.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/yaml/profile.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/yaml/scanner.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/yaml/validator.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser/yaml.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/parser.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/range_utils.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/alerts.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/ast.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/attributes.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/block_quotes.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/blocks.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/chunk_options.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/citations.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/code_blocks.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/crossrefs.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/definitions.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/fenced_divs.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/headings.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/inlines.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/kind.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/links.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/lists.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/math.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/raw_tex.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/references.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/shortcodes.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/tables.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/yaml.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax/yaml_ast.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-parser/src/syntax.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/pyproject.toml +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/bib/bibtex.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/bib/csl_json.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/bib/csl_yaml.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/bib/index.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/bib/ris.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/bib.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/cache.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/cli.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/config/formatter_presets.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/config/types/schema_helpers.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/config.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/diagnostic_renderer.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/directives.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/external_formatters_common.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/external_formatters_sync.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/external_tools_common.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/formatter.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/includes.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lib.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/code_block_collector.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/diagnostics.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/external_linters/clippy.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/external_linters/eslint.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/external_linters/jarl.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/external_linters/ruff.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/external_linters/shellcheck.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/external_linters/staticcheck.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/external_linters.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/external_linters_sync.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/index.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/metadata_diagnostics.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/offsets.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/adjacent_footnote_refs.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/chunk_label_spaces.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/citation_keys.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/crossref_as_link_target.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/duplicate_references.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/emoji_aliases.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/empty_list_item.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/figure_crossref_captions.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/footnote_ref_in_footnote_def.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/heading_eaten_attrs.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/heading_hierarchy.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/heading_strip_comments_residue.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/html_entities.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/link_text_is_url.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/math_content.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/missing_chunk_labels.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/stray_fenced_div_markers.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/undefined_anchor.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/undefined_references.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules/unused_definitions.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/rules.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter/runner.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/linter.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/config.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/context.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/conversions.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/dispatch.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/documents.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/global_state.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/code_actions.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/completion.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/diagnostics.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/document_links.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/document_symbols.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/file_rename.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/file_watcher.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/folding_ranges.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/footnote_conversion.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/formatting.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/goto_definition.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/heading_link_conversion.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/hover.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/link_conversion.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/list_conversion.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/prepare_rename.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/references.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/rename.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/shortcode_args.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers/workspace_symbols.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/handlers.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/helpers.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/navigation.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/symbols.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/task_pool.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/testing.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp/uri_ext.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/lsp.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/main.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/metadata/bibliography.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/metadata/citations.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/metadata/project.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/metadata/references.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/metadata/yaml.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/metadata.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/parser.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/range_utils.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/salsa.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/syntax.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/utils.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.0}/src/yaml_engine.rs +0 -0
- {panache_cli-2.54.0 → panache_cli-2.55.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.
|
|
1154
|
+
version = "2.55.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.
|
|
1197
|
+
version = "0.13.0"
|
|
1198
1198
|
dependencies = [
|
|
1199
1199
|
"insta",
|
|
1200
1200
|
"log",
|
|
@@ -1209,7 +1209,7 @@ dependencies = [
|
|
|
1209
1209
|
|
|
1210
1210
|
[[package]]
|
|
1211
1211
|
name = "panache-parser"
|
|
1212
|
-
version = "0.17.
|
|
1212
|
+
version = "0.17.1"
|
|
1213
1213
|
dependencies = [
|
|
1214
1214
|
"entities",
|
|
1215
1215
|
"insta",
|
|
@@ -7,7 +7,7 @@ authors = ["Johan Larsson <johan@jolars.co>"]
|
|
|
7
7
|
|
|
8
8
|
[package]
|
|
9
9
|
name = "panache"
|
|
10
|
-
version = "2.
|
|
10
|
+
version = "2.55.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"
|
|
@@ -49,8 +49,8 @@ path = "src/main.rs"
|
|
|
49
49
|
required-features = ["cli"]
|
|
50
50
|
|
|
51
51
|
[dependencies]
|
|
52
|
-
panache-formatter = { path = "crates/panache-formatter", version = "0.
|
|
53
|
-
panache-parser = { path = "crates/panache-parser", version = "0.17.
|
|
52
|
+
panache-formatter = { path = "crates/panache-formatter", version = "0.13.0" }
|
|
53
|
+
panache-parser = { path = "crates/panache-parser", version = "0.17.1", features = [
|
|
54
54
|
"serde",
|
|
55
55
|
"schema",
|
|
56
56
|
] }
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.13.0](https://github.com/jolars/panache/compare/panache-formatter-v0.12.0...panache-formatter-v0.13.0) (2026-06-15)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
- **formatter:** nest broken binary math continuations by `math-indent` ([`5948ca1`](https://github.com/jolars/panache/commit/5948ca15bb1fa1350e91dbf8fdfc5e11f0e40c32))
|
|
7
|
+
- **formatter:** default `math-indent` to 2 ([`3d0422b`](https://github.com/jolars/panache/commit/3d0422b8355e57b2d9e04b0ac86128da414b75b2))
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
- **formatter:** fix(formatter): charge math-indent against display line-break budget ([`754faaa`](https://github.com/jolars/panache/commit/754faaa451ae418a681237f86bc5ad3d6096c92f))
|
|
11
|
+
- **parser:** claim trailing caption for table-first list item ([`a09f066`](https://github.com/jolars/panache/commit/a09f066a9493f3f626b44691023c59c151caafb8))
|
|
12
|
+
- **formatter:** re-emit list marker for table-first item ([`9633b86`](https://github.com/jolars/panache/commit/9633b8632a2f075df3d59852cf414933c9aaba44))
|
|
13
|
+
|
|
14
|
+
### Dependencies
|
|
15
|
+
- updated crates/panache-parser to v0.17.1
|
|
16
|
+
|
|
3
17
|
## [0.12.0](https://github.com/jolars/panache/compare/panache-formatter-v0.11.0...panache-formatter-v0.12.0) (2026-06-13)
|
|
4
18
|
|
|
5
19
|
### Features
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "panache-formatter"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.13.0"
|
|
4
4
|
edition.workspace = true
|
|
5
5
|
include = [
|
|
6
6
|
"/src/**/*",
|
|
@@ -18,7 +18,7 @@ keywords = ["quarto", "pandoc", "markdown", "formatter"]
|
|
|
18
18
|
categories = ["text-processing"]
|
|
19
19
|
|
|
20
20
|
[dependencies]
|
|
21
|
-
panache-parser = { path = "../panache-parser", version = "0.17.
|
|
21
|
+
panache-parser = { path = "../panache-parser", version = "0.17.1" }
|
|
22
22
|
log = { version = "0.4.31", features = ["release_max_level_debug"] }
|
|
23
23
|
rowan = "0.16.1"
|
|
24
24
|
unicode-width = "0.2"
|
|
@@ -200,7 +200,7 @@ impl Default for Config {
|
|
|
200
200
|
formatter_extensions: FormatterExtensions::for_flavor(flavor),
|
|
201
201
|
line_ending: Some(LineEnding::Auto),
|
|
202
202
|
line_width: 80,
|
|
203
|
-
math_indent:
|
|
203
|
+
math_indent: 2,
|
|
204
204
|
math_delimiter_style: MathDelimiterStyle::default(),
|
|
205
205
|
tab_stops: TabStopMode::Normalize,
|
|
206
206
|
tab_width: 4,
|
|
@@ -536,8 +536,13 @@ pub(super) fn format_inline_node(node: &SyntaxNode, config: &Config) -> String {
|
|
|
536
536
|
result.push_str(&math::format_math(&content, &opts));
|
|
537
537
|
result.push('\n');
|
|
538
538
|
} else {
|
|
539
|
-
// Process content: trim
|
|
540
|
-
|
|
539
|
+
// Process content: trim surrounding newlines (NOT leading spaces)
|
|
540
|
+
// and trailing whitespace, strip common leading whitespace, then
|
|
541
|
+
// re-indent every line by `math_indent`. Trimming only leading
|
|
542
|
+
// newlines keeps each line's true indent visible to `min_indent`,
|
|
543
|
+
// so the re-indent is idempotent: a later pass strips the pad as
|
|
544
|
+
// common indentation before re-applying it, rather than stacking.
|
|
545
|
+
let trimmed_content = content.trim_start_matches(['\n', '\r']).trim_end();
|
|
541
546
|
if !trimmed_content.is_empty() {
|
|
542
547
|
// Find minimum indentation across all non-empty lines
|
|
543
548
|
let min_indent = trimmed_content
|
|
@@ -547,12 +552,18 @@ pub(super) fn format_inline_node(node: &SyntaxNode, config: &Config) -> String {
|
|
|
547
552
|
.min()
|
|
548
553
|
.unwrap_or(0);
|
|
549
554
|
|
|
550
|
-
|
|
555
|
+
let pad = " ".repeat(config.math_indent);
|
|
556
|
+
// Strip common indentation, then re-indent each line.
|
|
551
557
|
for line in trimmed_content.lines() {
|
|
552
|
-
if line.len() >= min_indent {
|
|
553
|
-
|
|
558
|
+
let stripped = if line.len() >= min_indent {
|
|
559
|
+
&line[min_indent..]
|
|
554
560
|
} else {
|
|
555
|
-
|
|
561
|
+
line
|
|
562
|
+
};
|
|
563
|
+
// Skip padding blank lines to avoid trailing whitespace.
|
|
564
|
+
if !stripped.is_empty() {
|
|
565
|
+
result.push_str(&pad);
|
|
566
|
+
result.push_str(stripped);
|
|
556
567
|
}
|
|
557
568
|
result.push('\n');
|
|
558
569
|
}
|
|
@@ -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);
|
{panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/math/STYLE.md
RENAMED
|
@@ -104,9 +104,11 @@ Returned unchanged, never reflowed:
|
|
|
104
104
|
every later relation starts a continuation **aligned under the first
|
|
105
105
|
relation's column**. Then any relation segment that is still over-width
|
|
106
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.
|
|
108
|
-
|
|
109
|
-
is
|
|
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:
|
|
110
112
|
|
|
111
113
|
```
|
|
112
114
|
A = aaaaaaaaaa
|
{panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/math/linebreak.rs
RENAMED
|
@@ -52,6 +52,11 @@
|
|
|
52
52
|
//! stays on one line, like an unbreakable long word in prose reflow. Inline and
|
|
53
53
|
//! environment-body math are not line-broken.
|
|
54
54
|
//!
|
|
55
|
+
//! On top of that bare geometry, each binary continuation is nested one extra
|
|
56
|
+
//! `math-indent` step (the `cont_indent` argument) so the `+ term` rows sit
|
|
57
|
+
//! below — not flush with — the head/right-hand side they hang under. Relation
|
|
58
|
+
//! continuations keep the bare alignment so relation operators stay in a column.
|
|
59
|
+
//!
|
|
55
60
|
//! ## Idempotency
|
|
56
61
|
//!
|
|
57
62
|
//! Indents are derived from the *logical* row (recomputed every pass), never
|
|
@@ -78,7 +83,17 @@ struct Break {
|
|
|
78
83
|
/// Break one logical free-display row into physical content lines (no base
|
|
79
84
|
/// math-indent, no trailing `\\` — the caller adds those). A row that fits, or
|
|
80
85
|
/// that has no usable relation chain, is returned on one line unchanged.
|
|
81
|
-
|
|
86
|
+
///
|
|
87
|
+
/// `cont_indent` (the block's `math-indent`) is added to every *binary*
|
|
88
|
+
/// continuation line so the broken `+ term` rows nest one indent step deeper
|
|
89
|
+
/// than the head/right-hand side they hang under. Relation continuations are
|
|
90
|
+
/// not shifted, so the relation operators stay column-aligned. With
|
|
91
|
+
/// `cont_indent == 0` the layout is the bare alignment geometry.
|
|
92
|
+
pub(super) fn break_free_row(
|
|
93
|
+
elems: &[SyntaxElement],
|
|
94
|
+
line_width: usize,
|
|
95
|
+
cont_indent: usize,
|
|
96
|
+
) -> Vec<String> {
|
|
82
97
|
// The unbroken, canonical single-line form — also the exact bytes the old
|
|
83
98
|
// code emitted, so a row that fits is byte-identical to before.
|
|
84
99
|
let single = render::render_inline(elems).trim().to_string();
|
|
@@ -94,13 +109,14 @@ pub(super) fn break_free_row(elems: &[SyntaxElement], line_width: usize) -> Vec<
|
|
|
94
109
|
.collect();
|
|
95
110
|
|
|
96
111
|
// Zero relations: a standalone binary chain. With no relation, the chain's
|
|
97
|
-
// first term *is* the head, so each `+ term` aligns
|
|
98
|
-
// 0) — the same rule the
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
//
|
|
112
|
+
// first term *is* the head, so each `+ term` aligns under it, nested by
|
|
113
|
+
// `cont_indent` (the block's math-indent; 0 ⇒ flush) — the same rule the
|
|
114
|
+
// relation cases follow (a binary continuation aligns under the first term of
|
|
115
|
+
// its right-hand side, plus the continuation indent). A row with no top-level
|
|
116
|
+
// binary op either (e.g. a lone wide `\frac`) falls through
|
|
117
|
+
// `break_binary_segment`'s empty-`bins` guard and stays on one (over-width) line.
|
|
102
118
|
if rels.is_empty() {
|
|
103
|
-
return break_binary_segment(elems, 0,
|
|
119
|
+
return break_binary_segment(elems, 0, cont_indent, line_width);
|
|
104
120
|
}
|
|
105
121
|
|
|
106
122
|
// Relation continuations align under the first relation's column; binary
|
|
@@ -114,7 +130,7 @@ pub(super) fn break_free_row(elems: &[SyntaxElement], line_width: usize) -> Vec<
|
|
|
114
130
|
} else {
|
|
115
131
|
prefix_width + 1
|
|
116
132
|
};
|
|
117
|
-
let bin_indent = rel_indent + BINARY_NEST;
|
|
133
|
+
let bin_indent = rel_indent + BINARY_NEST + cont_indent;
|
|
118
134
|
|
|
119
135
|
// One relation: the whole row is a single segment. It keeps the lone relation
|
|
120
136
|
// on the opening line; an over-width binary RHS breaks before each `+`, each
|
|
@@ -311,8 +327,14 @@ mod tests {
|
|
|
311
327
|
node.children_with_tokens().collect()
|
|
312
328
|
}
|
|
313
329
|
|
|
330
|
+
/// Bare alignment geometry (no extra continuation indent).
|
|
314
331
|
fn lines(content: &str, width: usize) -> Vec<String> {
|
|
315
|
-
break_free_row(&elems(content), width)
|
|
332
|
+
break_free_row(&elems(content), width, 0)
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/// Layout with a continuation indent step (mirrors a non-zero `math-indent`).
|
|
336
|
+
fn lines_nested(content: &str, width: usize, cont_indent: usize) -> Vec<String> {
|
|
337
|
+
break_free_row(&elems(content), width, cont_indent)
|
|
316
338
|
}
|
|
317
339
|
|
|
318
340
|
fn rel_indices(content: &str) -> Vec<usize> {
|
|
@@ -423,6 +445,45 @@ mod tests {
|
|
|
423
445
|
);
|
|
424
446
|
}
|
|
425
447
|
|
|
448
|
+
#[test]
|
|
449
|
+
fn continuation_indent_nests_binary_terms_no_relation() {
|
|
450
|
+
// A non-zero continuation indent nests each `+ term` one step under the
|
|
451
|
+
// head instead of flush.
|
|
452
|
+
assert_eq!(
|
|
453
|
+
lines_nested("aaaa + bbbb + cccc + dddd", 12, 2),
|
|
454
|
+
vec!["aaaa", " + bbbb", " + cccc", " + dddd"],
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
#[test]
|
|
459
|
+
fn continuation_indent_nests_binary_terms_one_relation() {
|
|
460
|
+
// The `+ term` rows nest one step past the relation's right-hand side
|
|
461
|
+
// (bare `bin_indent` 4 + continuation indent 2 = 6).
|
|
462
|
+
assert_eq!(
|
|
463
|
+
lines_nested("A = aaaaaaaaaa + bbbbbbbbbb + cccccccccc", 20, 2),
|
|
464
|
+
vec!["A = aaaaaaaaaa", " + bbbbbbbbbb", " + cccccccccc"],
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
#[test]
|
|
469
|
+
fn continuation_indent_leaves_relation_columns_aligned() {
|
|
470
|
+
// Relation continuations stay aligned under the first `=`; only the
|
|
471
|
+
// binary terms pick up the extra continuation indent.
|
|
472
|
+
assert_eq!(
|
|
473
|
+
lines_nested(
|
|
474
|
+
"A = aaaaaaaaaa + bbbbbbbbbb = cccccccccc + dddddddddd",
|
|
475
|
+
20,
|
|
476
|
+
2
|
|
477
|
+
),
|
|
478
|
+
vec![
|
|
479
|
+
"A = aaaaaaaaaa",
|
|
480
|
+
" + bbbbbbbbbb",
|
|
481
|
+
" = cccccccccc",
|
|
482
|
+
" + dddddddddd",
|
|
483
|
+
],
|
|
484
|
+
);
|
|
485
|
+
}
|
|
486
|
+
|
|
426
487
|
#[test]
|
|
427
488
|
fn zero_relation_no_binary_stays_one_line() {
|
|
428
489
|
// No relation and no top-level binary (the ops live inside the `\frac`
|
{panache_cli-2.54.0 → panache_cli-2.55.0}/crates/panache-formatter/src/formatter/math/render.rs
RENAMED
|
@@ -36,7 +36,13 @@ fn render_display(top: &[SyntaxElement], opts: &MathFormatOptions) -> String {
|
|
|
36
36
|
|
|
37
37
|
for el in top {
|
|
38
38
|
if el.kind() == SyntaxKind::MATH_ENVIRONMENT {
|
|
39
|
-
flush_free_rows(
|
|
39
|
+
flush_free_rows(
|
|
40
|
+
&pending,
|
|
41
|
+
&flat_indent,
|
|
42
|
+
opts.line_width,
|
|
43
|
+
opts.math_indent,
|
|
44
|
+
&mut lines,
|
|
45
|
+
);
|
|
40
46
|
pending.clear();
|
|
41
47
|
if let Some(node) = el.as_node() {
|
|
42
48
|
lines.extend(render_environment_lines(node, 0, opts));
|
|
@@ -45,7 +51,13 @@ fn render_display(top: &[SyntaxElement], opts: &MathFormatOptions) -> String {
|
|
|
45
51
|
pending.push(el.clone());
|
|
46
52
|
}
|
|
47
53
|
}
|
|
48
|
-
flush_free_rows(
|
|
54
|
+
flush_free_rows(
|
|
55
|
+
&pending,
|
|
56
|
+
&flat_indent,
|
|
57
|
+
opts.line_width,
|
|
58
|
+
opts.math_indent,
|
|
59
|
+
&mut lines,
|
|
60
|
+
);
|
|
49
61
|
lines.join("\n")
|
|
50
62
|
}
|
|
51
63
|
|
|
@@ -61,13 +73,17 @@ fn flush_free_rows(
|
|
|
61
73
|
elems: &[SyntaxElement],
|
|
62
74
|
indent: &str,
|
|
63
75
|
line_width: usize,
|
|
76
|
+
cont_indent: usize,
|
|
64
77
|
lines: &mut Vec<String>,
|
|
65
78
|
) {
|
|
66
79
|
for row in split_logical_rows(elems) {
|
|
67
80
|
if row.is_blank() {
|
|
68
81
|
continue;
|
|
69
82
|
}
|
|
70
|
-
|
|
83
|
+
// Charge the flat math-indent against the budget so packed (and single)
|
|
84
|
+
// lines genuinely stay within `line_width` once the indent is prepended.
|
|
85
|
+
let budget = line_width.saturating_sub(indent.chars().count());
|
|
86
|
+
let physical = linebreak::break_free_row(&row.elems, budget, cont_indent);
|
|
71
87
|
let last = physical.len() - 1;
|
|
72
88
|
for (i, content) in physical.into_iter().enumerate() {
|
|
73
89
|
// The trailing `\\` (if any) rides the final physical line.
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.17.1](https://github.com/jolars/panache/compare/panache-parser-v0.17.0...panache-parser-v0.17.1) (2026-06-15)
|
|
4
|
+
|
|
5
|
+
### Bug Fixes
|
|
6
|
+
- **parser:** claim trailing caption for table-first list item ([`a09f066`](https://github.com/jolars/panache/commit/a09f066a9493f3f626b44691023c59c151caafb8))
|
|
7
|
+
|
|
3
8
|
## [0.17.0](https://github.com/jolars/panache/compare/panache-parser-v0.16.0...panache-parser-v0.17.0) (2026-06-13)
|
|
4
9
|
|
|
5
10
|
### Features
|
|
@@ -601,6 +601,92 @@ impl<'a> Parser<'a> {
|
|
|
601
601
|
Some(consumed.saturating_sub(1))
|
|
602
602
|
}
|
|
603
603
|
|
|
604
|
+
/// When a new list item's marker line *begins a table* that is followed by a
|
|
605
|
+
/// trailing caption (`- | a | b |\n | - | - |\n\n : cap` or the
|
|
606
|
+
/// `Table:`/`table:` keyword form), parse the whole table-with-caption as the
|
|
607
|
+
/// item's content here, at the marker line.
|
|
608
|
+
///
|
|
609
|
+
/// A marker-line table is normally buffered and recognized only at item
|
|
610
|
+
/// close via [`crate::parser::utils::list_item_buffer::ListItemBuffer`]'s
|
|
611
|
+
/// structural lift. That lift cannot see a *trailing* caption: the blank line
|
|
612
|
+
/// after the table flushes the buffer (`Table:` form), and a bare `: cap`
|
|
613
|
+
/// line is additionally claimed by the definition-list parser as a term/
|
|
614
|
+
/// definition (`: cap` form) — both before the caption ever reaches the
|
|
615
|
+
/// buffer. Parsing the table at the marker line instead lets the table
|
|
616
|
+
/// parser's own trailing-caption scan (`find_caption_after_table`) absorb the
|
|
617
|
+
/// caption, matching pandoc, which always treats `: cap` after a table as the
|
|
618
|
+
/// table's `Caption`, never a definition list.
|
|
619
|
+
///
|
|
620
|
+
/// Gated on a caption actually being present so the *no-caption* marker-line
|
|
621
|
+
/// table keeps its existing buffer-lift CST untouched. Returns the number of
|
|
622
|
+
/// source lines consumed beyond the list-marker line.
|
|
623
|
+
fn maybe_open_table_with_trailing_caption_in_new_list_item(&mut self) -> Option<usize> {
|
|
624
|
+
if !self.config.extensions.table_captions {
|
|
625
|
+
return None;
|
|
626
|
+
}
|
|
627
|
+
if !(self.config.extensions.simple_tables
|
|
628
|
+
|| self.config.extensions.multiline_tables
|
|
629
|
+
|| self.config.extensions.grid_tables
|
|
630
|
+
|| self.config.extensions.pipe_tables)
|
|
631
|
+
{
|
|
632
|
+
return None;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
let Some(Container::ListItem {
|
|
636
|
+
content_col,
|
|
637
|
+
buffer,
|
|
638
|
+
..
|
|
639
|
+
}) = self.containers.stack.last()
|
|
640
|
+
else {
|
|
641
|
+
return None;
|
|
642
|
+
};
|
|
643
|
+
// Only the marker line is buffered so far; a multi-segment buffer means
|
|
644
|
+
// more content already accumulated and this is not a fresh marker line.
|
|
645
|
+
if buffer.segment_count() != 1 {
|
|
646
|
+
return None;
|
|
647
|
+
}
|
|
648
|
+
// Cheap pre-filter: a table on the marker line begins with `|` or `+`.
|
|
649
|
+
let first = buffer.first_text()?;
|
|
650
|
+
if !matches!(
|
|
651
|
+
first.trim_start().as_bytes().first(),
|
|
652
|
+
Some(b'|') | Some(b'+')
|
|
653
|
+
) {
|
|
654
|
+
return None;
|
|
655
|
+
}
|
|
656
|
+
let content_col = *content_col;
|
|
657
|
+
|
|
658
|
+
let bq_depth = self.current_blockquote_depth();
|
|
659
|
+
let prefix = ContainerPrefix::from_scalars(bq_depth, content_col, bq_depth > 0, 0, true);
|
|
660
|
+
let window = StrippedLines::new(&self.lines, self.pos, &prefix);
|
|
661
|
+
|
|
662
|
+
// A caption-led table (`- : cap` / `- Table: cap` then table) is the
|
|
663
|
+
// sibling function's job; never double-handle it here.
|
|
664
|
+
if tables::is_caption_followed_by_table(&window, self.pos) {
|
|
665
|
+
return None;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// Probe into a throwaway builder: only commit when the marker-line table
|
|
669
|
+
// actually pulls in a trailing caption. Otherwise leave the line buffered
|
|
670
|
+
// so the no-caption structural lift produces its established CST.
|
|
671
|
+
let mut probe = GreenNodeBuilder::new();
|
|
672
|
+
let _ = try_parse_any_table_kind(&window, &mut probe, self.config)?;
|
|
673
|
+
let probe_root = SyntaxNode::new_root(probe.finish());
|
|
674
|
+
let has_caption = probe_root
|
|
675
|
+
.children()
|
|
676
|
+
.any(|c| c.kind() == SyntaxKind::TABLE_CAPTION);
|
|
677
|
+
if !has_caption {
|
|
678
|
+
return None;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
// Commit: emit the table (with its `TABLE_CAPTION`) as the list item's
|
|
682
|
+
// content and drop the buffered marker line so it isn't also emitted.
|
|
683
|
+
let consumed = try_parse_any_table_kind(&window, &mut self.builder, self.config)?;
|
|
684
|
+
if let Some(Container::ListItem { buffer, .. }) = self.containers.stack.last_mut() {
|
|
685
|
+
buffer.clear();
|
|
686
|
+
}
|
|
687
|
+
Some(consumed.saturating_sub(1))
|
|
688
|
+
}
|
|
689
|
+
|
|
604
690
|
/// CommonMark §5.2 rule #2: when a list marker is followed by ≥ 5 columns
|
|
605
691
|
/// of whitespace and non-empty content, the content begins as an indented
|
|
606
692
|
/// code block on the marker line. The marker parser collapses the post-
|
|
@@ -1202,6 +1288,11 @@ impl<'a> Parser<'a> {
|
|
|
1202
1288
|
if let Some(extras) = self.maybe_open_caption_table_in_new_list_item() {
|
|
1203
1289
|
return extras;
|
|
1204
1290
|
}
|
|
1291
|
+
if let Some(extras) =
|
|
1292
|
+
self.maybe_open_table_with_trailing_caption_in_new_list_item()
|
|
1293
|
+
{
|
|
1294
|
+
return extras;
|
|
1295
|
+
}
|
|
1205
1296
|
self.maybe_open_indented_code_in_new_list_item();
|
|
1206
1297
|
return self.dispatch_bq_after_list_item(finish);
|
|
1207
1298
|
}
|
|
@@ -1223,6 +1314,9 @@ impl<'a> Parser<'a> {
|
|
|
1223
1314
|
if let Some(extras) = self.maybe_open_caption_table_in_new_list_item() {
|
|
1224
1315
|
return extras;
|
|
1225
1316
|
}
|
|
1317
|
+
if let Some(extras) = self.maybe_open_table_with_trailing_caption_in_new_list_item() {
|
|
1318
|
+
return extras;
|
|
1319
|
+
}
|
|
1226
1320
|
self.maybe_open_indented_code_in_new_list_item();
|
|
1227
1321
|
return self.dispatch_bq_after_list_item(finish);
|
|
1228
1322
|
}
|
|
@@ -1265,6 +1359,9 @@ impl<'a> Parser<'a> {
|
|
|
1265
1359
|
if let Some(extras) = self.maybe_open_caption_table_in_new_list_item() {
|
|
1266
1360
|
return extras;
|
|
1267
1361
|
}
|
|
1362
|
+
if let Some(extras) = self.maybe_open_table_with_trailing_caption_in_new_list_item() {
|
|
1363
|
+
return extras;
|
|
1364
|
+
}
|
|
1268
1365
|
self.maybe_open_indented_code_in_new_list_item();
|
|
1269
1366
|
return self.dispatch_bq_after_list_item(finish);
|
|
1270
1367
|
}
|
|
@@ -1313,6 +1410,9 @@ impl<'a> Parser<'a> {
|
|
|
1313
1410
|
if let Some(extras) = self.maybe_open_caption_table_in_new_list_item() {
|
|
1314
1411
|
return extras;
|
|
1315
1412
|
}
|
|
1413
|
+
if let Some(extras) = self.maybe_open_table_with_trailing_caption_in_new_list_item() {
|
|
1414
|
+
return extras;
|
|
1415
|
+
}
|
|
1316
1416
|
self.maybe_open_indented_code_in_new_list_item();
|
|
1317
1417
|
self.dispatch_bq_after_list_item(finish)
|
|
1318
1418
|
}
|
|
@@ -2634,6 +2734,10 @@ impl<'a> Parser<'a> {
|
|
|
2634
2734
|
extras
|
|
2635
2735
|
} else if let Some(extras) = self.maybe_open_caption_table_in_new_list_item() {
|
|
2636
2736
|
extras
|
|
2737
|
+
} else if let Some(extras) =
|
|
2738
|
+
self.maybe_open_table_with_trailing_caption_in_new_list_item()
|
|
2739
|
+
{
|
|
2740
|
+
extras
|
|
2637
2741
|
} else {
|
|
2638
2742
|
self.maybe_open_indented_code_in_new_list_item();
|
|
2639
2743
|
self.dispatch_bq_after_list_item(finish)
|
|
@@ -3656,6 +3760,32 @@ impl<'a> Parser<'a> {
|
|
|
3656
3760
|
/// Pandoc parses `Term\n: # Heading\n Some text` as DefinitionList where the
|
|
3657
3761
|
/// definition contains [Header, Plain]; the `# Heading` line is a real Header
|
|
3658
3762
|
/// inside the definition, not text that happens to start with `#`.
|
|
3763
|
+
/// Try each enabled table kind in turn (Grid → Multiline → Pipe → Simple),
|
|
3764
|
+
/// emitting the first match into `builder` and returning the lines consumed.
|
|
3765
|
+
/// Every kind validates before its first `start_node`, so on a full miss the
|
|
3766
|
+
/// builder is left untouched and `None` is returned. Mirrors the dispatcher's
|
|
3767
|
+
/// `first_kind_at` cascade for the list-item marker-line table paths.
|
|
3768
|
+
fn try_parse_any_table_kind(
|
|
3769
|
+
window: &StrippedLines,
|
|
3770
|
+
builder: &mut GreenNodeBuilder<'static>,
|
|
3771
|
+
config: &ParserOptions,
|
|
3772
|
+
) -> Option<usize> {
|
|
3773
|
+
let mut consumed = None;
|
|
3774
|
+
if config.extensions.grid_tables {
|
|
3775
|
+
consumed = tables::try_parse_grid_table(window, builder, config);
|
|
3776
|
+
}
|
|
3777
|
+
if consumed.is_none() && config.extensions.multiline_tables {
|
|
3778
|
+
consumed = tables::try_parse_multiline_table(window, builder, config);
|
|
3779
|
+
}
|
|
3780
|
+
if consumed.is_none() && config.extensions.pipe_tables {
|
|
3781
|
+
consumed = tables::try_parse_pipe_table(window, builder, config);
|
|
3782
|
+
}
|
|
3783
|
+
if consumed.is_none() && config.extensions.simple_tables {
|
|
3784
|
+
consumed = tables::try_parse_simple_table(window, builder, config);
|
|
3785
|
+
}
|
|
3786
|
+
consumed
|
|
3787
|
+
}
|
|
3788
|
+
|
|
3659
3789
|
fn emit_definition_plain_or_heading(
|
|
3660
3790
|
builder: &mut GreenNodeBuilder<'static>,
|
|
3661
3791
|
text: &str,
|