mdbook-plotly 0.3.0

A mdbook preprocessor that renders plot code blocks (e.g., ```plot) into interactive or static charts during book build.
Documentation
name: Release
permissions:
  contents: write
on:
  push:
    branches: [main, dev]
    tags:
      - 'v[0-9]+.*'
  pull_request:

jobs:
  # Static checks + tests for both feature combinations. Runs on every PR
  # and push so a doc change that breaks the USAGE.md schema, or any
  # regression, turns CI red before it reaches users.
  check:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        features: ["", "tui"]
    steps:
      - uses: actions/checkout@v6

      - uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy, rustfmt

      - uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: check-${{ matrix.features }}-${{ hashFiles('Cargo.lock') }}
          restore-keys: check-${{ matrix.features }}-

      - name: Clippy (-D warnings)
        run: |
          FEAT=""
          if [ -n "${{ matrix.features }}" ]; then FEAT="--features ${{ matrix.features }}"; fi
          cargo clippy --locked --all-targets $FEAT -- -D warnings

      - name: Test (incl. USAGE.md schema)
        run: |
          FEAT=""
          if [ -n "${{ matrix.features }}" ]; then FEAT="--features ${{ matrix.features }}"; fi
          cargo test --locked $FEAT

      - name: Format check
        run: cargo fmt --check

  # Validates the plot generator schema against the parser: both language
  # files must parse, stay in sync, and every embedded example must produce
  # valid chart input.
  docs-schema-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - uses: dtolnay/rust-toolchain@stable

      - uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: docs-schema-${{ hashFiles('Cargo.lock') }}
          restore-keys: docs-schema-

      - name: Plot schema test
        run: cargo test --locked --features tui --test test_plot_schema

  # Renders key views through ratatui::TestBackend and asserts structure,
  # labels, and the paper palette, plus generator form logic.
  tui-visual-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - uses: dtolnay/rust-toolchain@stable

      - uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: tui-visual-${{ hashFiles('Cargo.lock') }}
          restore-keys: tui-visual-

      - name: Generator and visual regression tests
        run: cargo test --locked --features tui --test test_plotgen --test test_tui_visual

  # Creates the GitHub Release from docs/CHANGELOG.md when a v* tag is pushed.
  create-release:
    if: startsWith(github.ref, 'refs/tags/v')
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: taiki-e/create-gh-release-action@v1
        with:
          changelog: docs/CHANGELOG.md
          token: ${{ secrets.GITHUB_TOKEN }}

  # Builds both variants (slim and `-tui`) for every supported target and
  # uploads them under the names defined in docs/RELEASE.md, each with a
  # matching .sha256 checksum.
  upload-assets:
    if: startsWith(github.ref, 'refs/tags/v')
    needs: create-release
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - target: aarch64-apple-darwin
            os: macos-latest
            features: ""
          - target: aarch64-apple-darwin
            os: macos-latest
            features: "tui"
          - target: x86_64-apple-darwin
            os: macos-latest
            features: ""
          - target: x86_64-apple-darwin
            os: macos-latest
            features: "tui"
          - target: x86_64-pc-windows-msvc
            os: windows-latest
            features: ""
          - target: x86_64-pc-windows-msvc
            os: windows-latest
            features: "tui"
          - target: x86_64-unknown-linux-gnu
            os: ubuntu-latest
            features: ""
          - target: x86_64-unknown-linux-gnu
            os: ubuntu-latest
            features: "tui"
          - target: x86_64-unknown-linux-musl
            os: ubuntu-latest
            features: ""
          - target: x86_64-unknown-linux-musl
            os: ubuntu-latest
            features: "tui"
          - target: aarch64-unknown-linux-musl
            os: ubuntu-latest
            features: ""
          - target: aarch64-unknown-linux-musl
            os: ubuntu-latest
            features: "tui"

    steps:
      - uses: actions/checkout@v6

      - name: Setup cross toolchain (musl / aarch64 linux)
        if: matrix.os == 'ubuntu-latest' && contains(matrix.target, 'musl')
        uses: taiki-e/setup-cross-toolchain-action@v1
        with:
          target: ${{ matrix.target }}

      - name: Install Rust target
        if: matrix.os != 'ubuntu-latest' || !contains(matrix.target, 'musl')
        run: rustup target add ${{ matrix.target }}

      - uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: release-${{ matrix.os }}-${{ matrix.target }}-${{ matrix.features }}-${{ hashFiles('Cargo.lock') }}
          restore-keys: release-${{ matrix.os }}-${{ matrix.target }}-

      - name: Build (locked, release)
        shell: bash
        run: |
          FEAT=""
          if [ -n "${{ matrix.features }}" ]; then FEAT="--features ${{ matrix.features }}"; fi
          cargo build --locked --release --target ${{ matrix.target }} $FEAT

      - name: Package + checksum (contract A)
        shell: bash
        env:
          VERSION: ${{ github.ref_name }}
          TARGET: ${{ matrix.target }}
          FEATURES: ${{ matrix.features }}
        run: |
          set -euo pipefail
          VERSION="${VERSION#v}"
          SUFFIX=""
          if [ -n "${FEATURES}" ]; then SUFFIX="-tui"; fi
          if [ "$RUNNER_OS" = "Windows" ]; then
            EXT="zip"
            BIN="mdbook-plotly.exe"
          else
            EXT="tar.gz"
            BIN="mdbook-plotly"
          fi
          DIR="target/${TARGET}/release"
          NAME="mdbook-plotly-${VERSION}-${TARGET}${SUFFIX}.${EXT}"
          if [ "$RUNNER_OS" = "Windows" ]; then
            powershell -NoProfile -Command "Compress-Archive -Force -Path '${DIR}/${BIN}' -DestinationPath '${NAME}'"
          else
            tar -C "${DIR}" -czf "${NAME}" "${BIN}"
          fi
          python3 - "$NAME" <<'PY'
          import hashlib, sys
          name = sys.argv[1]
          digest = hashlib.sha256(open(name, "rb").read()).hexdigest()
          with open(name + ".sha256", "w", encoding="ascii") as f:
              f.write(f"{digest}  {name}\n")
          PY
          ls -1 mdbook-plotly-*

      - name: Upload assets
        uses: softprops/action-gh-release@v2
        with:
          files: |
            mdbook-plotly-*.tar.gz
            mdbook-plotly-*.zip
            mdbook-plotly-*.sha256
          token: ${{ secrets.GITHUB_TOKEN }}