mdtablefix 0.6.1

`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:

# A push to a pull request supersedes the run already in flight, and there is
# nothing left to learn from the superseded one. Cancellation is conditioned
# on the event so a push to `main`, a schedule, or a dispatch, none of which
# has a successor waiting, always runs to completion.
concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}

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@6dea5677a84fec60ca51b07202570e3af12ffdb4
      - name: Install ripgrep
        run: cargo binstall --no-confirm --locked ripgrep@15.2.0
      - name: Install mdtablefix
        # `make check-fmt` runs `mdtablefix --check --git`; 0.6.0 is the
        # first release with `--check` and `--git`.
        uses: leynos/shared-actions/.github/actions/install-mdtablefix@a5765019912a8ab6882b12db049c7cde635f3a85
        with:
          version: "0.6.0"

      - name: Format
        run: make check-fmt
      - name: Markdown lint
        # The comment said v20 and the SHA does not: `21c1be1b` is the commit
        # the `v24.2.0` tag object points at, whose message is "Update to
        # version 24.2.0." The pin is unchanged; only the label was wrong.
        uses: DavidAnson/markdownlint-cli2-action@21c1be1b93ad9ed58fa840aacc3f279cde2a72ff  # v24.2.0
        with:
          globs: '**/*.md'
      - name: Lint
        run: make lint
      - name: Test and Measure Coverage
        # Coverage here is for the local ratchet and nothing else. The report
        # is neither published (`publish-artefact: 'false'` keeps the action
        # from archiving it) nor sent to CodeScene: a pull request from a
        # fork cannot read `secrets.CS_ACCESS_TOKEN`, so an upload step here is
        # silently inert for exactly the changes that most need reviewing, and
        # a lane that holds the token at all is a lane a fork's workflow edit
        # could try to reach. `coverage-main.yml` owns both persistent outputs.
        #
        # The baseline paths are the action's defaults, which is what makes
        # this ratchet comparable with the one the main publisher writes: both
        # read and write `.coverage-baseline.rust`.
        uses: leynos/shared-actions/.github/actions/generate-coverage@a5765019912a8ab6882b12db049c7cde635f3a85
        with:
          output-path: lcov.info
          format: lcov
          with-ratchet: 'true'
          publish-artefact: 'false'

  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@6dea5677a84fec60ca51b07202570e3af12ffdb4
        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@6dea5677a84fec60ca51b07202570e3af12ffdb4
        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