mdtablefix 0.6.0

`mdtablefix` unb0rks and reflows Markdown tables so that each column has a uniform width. When the `--wrap` option is used, it also wraps paragraphs and list items to 80 columns.
Documentation
name: CI

'on':
  pull_request:
    types: [opened, synchronize, reopened]
  workflow_dispatch:

jobs:
  build-test:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    env:
      CARGO_TERM_COLOR: always
      BUILD_PROFILE: debug
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
      - name: Setup Rust
        uses: leynos/shared-actions/.github/actions/setup-rust@6b5cdc2d4c0bb72cafd5a66d24d248ac25827db9
      - name: Install ripgrep
        run: cargo binstall --no-confirm --locked ripgrep@15.2.0
      - name: Format
        run: make check-fmt
      - name: Markdown lint
        uses: DavidAnson/markdownlint-cli2-action@21c1be1b93ad9ed58fa840aacc3f279cde2a72ff  # v20
        with:
          globs: |
            **/*.md
            !**/target/**
            !**/dist/**
      - name: Lint
        run: make lint
      - name: Test and Measure Coverage
        uses: leynos/shared-actions/.github/actions/generate-coverage@6b5cdc2d4c0bb72cafd5a66d24d248ac25827db9
        with:
          output-path: lcov.info
          format: lcov
      - name: Upload coverage data to CodeScene
        env:
          CS_ACCESS_TOKEN: ${{ secrets.CS_ACCESS_TOKEN }}
        if: ${{ env.CS_ACCESS_TOKEN }}
        uses: leynos/shared-actions/.github/actions/upload-codescene-coverage@6b5cdc2d4c0bb72cafd5a66d24d248ac25827db9

        with:
          format: lcov
          access-token: ${{ env.CS_ACCESS_TOKEN }}
          installer-checksum: ${{ vars.CODESCENE_CLI_SHA256 }}


  windows-atomic-contract:
    # The atomic replacement contract is platform-sensitive. The swap depends
    # on rename semantics that differ between POSIX and Windows, and on the
    # destination's read-only state, which Windows records as a file attribute
    # rather than as a mode bit. The suites that assert it drive the library
    # helpers and the CLI against a read-only destination, so they run on the
    # platform whose semantics they assert. The whole suite runs here too, so a
    # change that is correct on Unix but not on Windows is caught by the same
    # job rather than by the release that follows it.
    name: atomic write contract (windows)
    runs-on: windows-latest
    permissions:
      contents: read
    defaults:
      run:
        shell: bash
    env:
      CARGO_TERM_COLOR: always
      RUSTFLAGS: "-D warnings"
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
      - name: Setup Rust
        uses: leynos/shared-actions/.github/actions/setup-rust@6b5cdc2d4c0bb72cafd5a66d24d248ac25827db9
        with:
          install-binstall: false
          use-sccache: false
      - name: Test the atomic write contract
        # `--lib` is required, not incidental: the rollback a failed swap
        # performs after the destination was prepared is unreachable through a
        # real rename, so it is covered by a private, test-only seam in
        # `src/io.rs`, which only a unit-test build compiles.
        run: cargo test --all-features --no-fail-fast --lib --test rewrite_atomic --test in_place_atomic
      - name: Test the whole suite
        # Every target reports, rather than stopping at the first one that
        # fails. The checkout keeps the repository's LF line endings — see
        # `.gitattributes`, without which Git for Windows hands the suites
        # CRLF fixtures — so the byte-for-byte fixture and snapshot
        # comparisons match the output this tool writes here too.
        run: cargo test --all-features --no-fail-fast

  binstall-packaging:
    # Runner-backed dry run of the release packaging. It proves the crate
    # builds on each release platform and that the staged assets match the
    # cargo-binstall templates in Cargo.toml before a tag depends on it.
    name: binstall packaging (${{ matrix.target }})
    runs-on: ${{ matrix.runner }}
    permissions:
      contents: read
    defaults:
      run:
        shell: bash
    strategy:
      fail-fast: false
      matrix:
        include:
          - runner: ubuntu-latest
            os: linux
            arch: x86_64
            target: x86_64-unknown-linux-gnu
          - runner: macos-15
            os: macos
            arch: aarch64
            target: aarch64-apple-darwin
          # macOS runners are Apple silicon, so this row is the only check
          # that the Intel cross-compile the release publishes still links.
          - runner: macos-15
            os: macos
            arch: x86_64
            target: x86_64-apple-darwin
            is-foreign: true
          - runner: windows-latest
            os: windows
            arch: x86_64
            target: x86_64-pc-windows-msvc
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
      - name: Setup Rust
        uses: leynos/shared-actions/.github/actions/setup-rust@6b5cdc2d4c0bb72cafd5a66d24d248ac25827db9
        with:
          toolchain: 1.89.0
          install-binstall: false
          use-sccache: false
      - name: Add release target
        run: rustup target add --toolchain 1.89.0 ${{ matrix.target }}
      - name: Build the release binary
        run: cargo +1.89.0 build --release --bin mdtablefix --target ${{ matrix.target }}
      - name: Stage the release assets
        run: |
          set -euo pipefail
          binary_ext=""
          if [[ "${{ matrix.target }}" == *windows* ]]; then
            binary_ext=".exe"
          fi
          python_bin=python3
          command -v python3 >/dev/null 2>&1 || python_bin=python
          version="$("${python_bin}" -c \
            'import pathlib, tomllib; print(tomllib.loads(pathlib.Path("Cargo.toml").read_text(encoding="utf-8"))["package"]["version"])')"
          "${python_bin}" scripts/package_release_artifacts.py \
            --binary "target/${{ matrix.target }}/release/mdtablefix${binary_ext}" \
            --artifact-dir "dist/${{ matrix.os }}-${{ matrix.arch }}" \
            --version "${version}" \
            --target "${{ matrix.target }}" \
            --os "${{ matrix.os }}" \
            --arch "${{ matrix.arch }}"
          "${python_bin}" scripts/verify_binstall_layout.py \
            --artifact-dir "dist/${{ matrix.os }}-${{ matrix.arch }}" \
            --target "${{ matrix.target }}"
      - name: Run the packaged binary
        # Skipped where the target is not the runner's own architecture.
        if: ${{ !matrix.is-foreign }}
        run: |
          set -euo pipefail
          binary_ext=""
          if [[ "${{ matrix.target }}" == *windows* ]]; then
            binary_ext=".exe"
          fi
          python_bin=python3
          command -v python3 >/dev/null 2>&1 || python_bin=python
          staged="dist/${{ matrix.os }}-${{ matrix.arch }}"
          # Extract through Python: the three runner images ship different tar
          # implementations, and only the archive contents are under test here.
          "${python_bin}" -c 'import pathlib, sys, tarfile; archive = next(pathlib.Path(sys.argv[1]).glob("*.tar.gz")); tarfile.open(archive).extractall(sys.argv[2], filter="data")' \
            "${staged}" "${RUNNER_TEMP}"
          chmod +x "${RUNNER_TEMP}/mdtablefix${binary_ext}"
          "${RUNNER_TEMP}/mdtablefix${binary_ext}" --version