diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..5b6dc77 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,52 @@ +# API reference: one DocC archive per module (the .docc catalogs under Sources/), merged into one static site and +# published to GitHub Pages at https://mac4dstem.github.io/DiffractoKit/documentation/ on every tag. +# On a pull request the site is built and uploaded as an artifact only, so a broken catalog fails before the tag. +# +# No swift-docc-plugin: the kit takes no package dependencies (CLAUDE.md). `xcodebuild docbuild` builds the archives +# from the package's own schemes; `docc merge` (Xcode 16+) joins them. Needs Pages enabled with source "GitHub Actions" +# (repository Settings > Pages). Copied from CuboKit's pattern; the module list is read from the .docc catalogs. +name: Docs + +on: + push: + tags: ['*'] + pull_request: + paths: ['Sources/**/*.docc/**', '.github/workflows/docs.yml', 'tools/build-docs.sh'] + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: docs-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + runs-on: macos-latest + timeout-minutes: 60 + steps: + - uses: actions/checkout@v4 + - name: Select the newest Xcode + run: | + xcode=$(ls -d /Applications/Xcode*.app | sort -V | tail -1) + sudo xcode-select -s "$xcode" + xcodebuild -version + - name: Build the site + run: tools/build-docs.sh .docs-site /DiffractoKit + - uses: actions/upload-pages-artifact@v3 + with: + path: .docs-site + + deploy: + needs: build + if: startsWith(github.ref, 'refs/tags/') + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - id: deployment + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index 6b1a1cd..cbb0eff 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.xcresult tools/benchmarks/inputs/ tools/benchmarks/.build/ +.docs-site/ # Local session rules, kept on disk only CLAUDE.md diff --git a/Tests/Fixtures/README.md b/Tests/Fixtures/README.md new file mode 100644 index 0000000..dbb47f3 --- /dev/null +++ b/Tests/Fixtures/README.md @@ -0,0 +1,70 @@ +# Test fixtures + +One row per committed fixture file under `Tests/*/Fixtures/`: size, the script under `tools/` that names it (the generator or its +pin script; a few scripts write a whole directory; a script found only by file-name prefix, tool-folder name or test module is marked so), and a note where the origin is not the kit's own pinned reference. 55 files. + +Licence: every fixture is generated from this kit's own code and the pinned Python reference (see `CLAUDE.md`, Reference) and ships under the kit's GPL-3.0-or-later licence, except the rows marked *third party*. Nothing here is the owner's data: the committed text fixtures carry no owner path or name (checked by search), and real datasets are read from `$MACEM_DATA` and never copied into the repo. + +## Third party + +3 files, listed in the table below with the note *third party*. Keep their licence line when the files move. + +## All fixtures + +| File | Size | Generated by | Note | +|---|---|---|---| +| `DiffractoCoreTests/Fixtures/alpha_quartz_P3221.cif` | 924 B | `tools/slice-1/pins.py`, `tools/slice-2/pins.py` | | +| `DiffractoCoreTests/Fixtures/alpha_quartz_P3221_as_seeded.cif` | 712 B | `tools/slice-1/pins.py` | | +| `DiffractoCoreTests/Fixtures/calcite_R-3c_hex.cif` | 1.4 KB | `tools/slice-1/pins.py`, `tools/slice-2/pins.py` | | +| `DiffractoCoreTests/Fixtures/cdi2_P-3m1.cif` | 462 B | `tools/slice-1/pins.py`, `tools/slice-2/pins.py` | | +| `DiffractoCoreTests/Fixtures/cif-symmetry-pins.json` | 19.4 KB | `tools/cif-symmetry/pins.py` | | +| `DiffractoCoreTests/Fixtures/fluorapatite_P63m.cif` | 781 B | `tools/slice-1/pins.py`, `tools/slice-2/pins.py` | | +| `DiffractoCoreTests/Fixtures/gold_P1.cif` | 396 B | `tools/slice-1/pins.py`, `tools/slice-2/pins.py` | | +| `DiffractoCoreTests/Fixtures/gold_centring_ops.cif` | 440 B | `tools/slice-1/pins.py` | | +| `DiffractoCoreTests/Fixtures/ideal_hcp_P1.cif` | 504 B | `tools/slice-1/pins.py` | | +| `DiffractoCoreTests/Fixtures/magnesium_P63mmc.cif` | 401 B | `tools/slice-4/pins.py` | | +| `DiffractoCoreTests/Fixtures/magnesium_P63mmc_24ops.cif` | 896 B | `tools/slice-1/pins.py` | | +| `DiffractoCoreTests/Fixtures/mp-import/input-aluminium-v3.json` | 1.6 KB | `tools/mp-import/pins.py` | third party: Materials Project export; licence terms to be confirmed by Paul | +| `DiffractoCoreTests/Fixtures/mp-import/input-magnesiumJSON.json` | 1.1 KB | `tools/mp-import/pins.py` | third party: Materials Project export; licence terms to be confirmed by Paul | +| `DiffractoCoreTests/Fixtures/mp-import/input-siliconJSON.json` | 2.9 KB | `tools/mp-import/pins.py` | third party: Materials Project export; licence terms to be confirmed by Paul | +| `DiffractoCoreTests/Fixtures/mp-import/pymatgen-pins.json` | 6.3 KB | `tools/mp-import/pins.py` | | +| `DiffractoCoreTests/Fixtures/presets-pins.json` | 21.1 KB | `tools/presets/pins.py` | | +| `DiffractoCoreTests/Fixtures/pyrite_Pa-3.cif` | 1.1 KB | `tools/slice-1/pins.py`, `tools/slice-2/pins.py` | | +| `DiffractoCoreTests/Fixtures/pyrite_Pa-3_as_seeded.cif` | 787 B | `tools/slice-1/pins.py` | | +| `DiffractoCoreTests/Fixtures/refuter_F2a_Mg_shifted.cif` | 529 B | `tools/slice-1b/pins.py` (name prefix) | | +| `DiffractoCoreTests/Fixtures/refuter_F2c_Au_shifted_exactdecimals.cif` | 588 B | `tools/slice-1b/pins.py` (name prefix) | | +| `DiffractoCoreTests/Fixtures/refuter_F2d_NaCl_shifted.cif` | 703 B | `tools/slice-1b/pins.py` (name prefix) | | +| `DiffractoCoreTests/Fixtures/refuter_F2e_quartz_shifted.cif` | 747 B | `tools/slice-1b/pins.py` (name prefix) | | +| `DiffractoCoreTests/Fixtures/refuter_F2f_Mg_loop_0.37.cif` | 1.5 KB | `tools/slice-1b/pins.py` (name prefix) | | +| `DiffractoCoreTests/Fixtures/refuter_F3_super7.cif` | 737 B | `tools/slice-1b/pins.py` | | +| `DiffractoCoreTests/Fixtures/refuter_P1_cubic_1fe.cif` | 470 B | `tools/slice-1b/pins.py` (name prefix) | | +| `DiffractoCoreTests/Fixtures/refuter_corundum_rh_p1.cif` | 1.3 KB | `tools/slice-1b/pins.py` (name prefix) | | +| `DiffractoCoreTests/Fixtures/refuter_mixed_centred.cif` | 561 B | `tools/slice-1b/pins.py` (name prefix) | | +| `DiffractoCoreTests/Fixtures/rocksalt_Fm-3m_192ops.cif` | 3.5 KB | `tools/slice-1/pins.py`, `tools/slice-2/pins.py` | | +| `DiffractoCoreTests/Fixtures/silicon_Fd-3m.cif` | 498 B | `tools/slice-1/pins.py`, `tools/slice-2/pins.py` | | +| `DiffractoCoreTests/Fixtures/slice-1-pins.json` | 2.7 MB | `tools/slice-1/pins.py`, `tools/slice-1b/pins.py` | | +| `DiffractoCoreTests/Fixtures/slice-1b-pins.json` | 2.2 MB | `tools/slice-1b/pins.py` | | +| `DiffractoCoreTests/Fixtures/tetragonal-pins.json` | 14.3 KB | `tools/kit-0.0.4/tetragonal-pins.py` | | +| `DiffractoCoreTests/Fixtures/tetragonal_a_equals_c.cif` | 387 B | `tools/slice-1/pins.py` | | +| `DiffractoCoreTests/Fixtures/tetragonal_a_equals_c_4ops.cif` | 623 B | `tools/slice-1/pins.py` | | +| `DiffractoCoreTests/Fixtures/ws2_2H.cif` | 568 B | `tools/slice-1/pins.py`, `tools/slice-2/pins.py` | | +| `DiffractoGeometryTests/Fixtures/indexing-display-pins.json` | 2.3 KB | `tools/mactem-pieces/indexing-display-pins.py` | | +| `DiffractoGeometryTests/Fixtures/q-pins.json` | 129.3 KB | `tools/kit-0.0.4/q-pins.py` | | +| `DiffractoGeometryTests/Fixtures/ring-overlay-pins.json` | 4.5 KB | `tools/mactem-pieces/ring-overlay-pins.py` | | +| `DiffractoGeometryTests/Fixtures/slice-3-index-pins.json` | 4.7 MB | `tools/slice-3/index-pins.py` | | +| `DiffractoGeometryTests/Fixtures/slice-3-ring-pins.json` | 139.8 KB | `tools/kit-0.0.4/q-pins.py`, `tools/slice-3/ring-pins.py` | | +| `DiffractoGeometryTests/Fixtures/slice-3b-apps-onone.json` | 133.3 KB | `tools/slice-3b/apps-parity/run.sh` | | +| `DiffractoGeometryTests/Fixtures/slice-3b-apps.json` | 133.3 KB | `tools/slice-3b/apps-parity/main.swift`, `tools/slice-3b/apps-parity/run.sh` | | +| `DiffractoGeometryTests/Fixtures/slice-3b-sweep.json` | 8.2 KB | `tools/slice-3b/sweep.py` | | +| `DiffractoOrientationTests/Fixtures/acom-matcher-pins.json` | 526.1 KB | `tools/acom-matcher/pins.py` | | +| `DiffractoOrientationTests/Fixtures/orix-direction-pins.json` | 1.5 MB | `tools/orix/direction-pins.py` | | +| `DiffractoOrientationTests/Fixtures/orix-disorientation-pins.json` | 1.5 MB | `tools/orix/disorientation-pins.py` | | +| `DiffractoOrientationTests/Fixtures/orix-ipf-pins.json` | 484.0 KB | `tools/orix/ipf-pins.py` | | +| `DiffractoOrientationTests/Fixtures/py4dstem-family-pins.json` | 1005.7 KB | `tools/symmetry/family-pins.py` | | +| `DiffractoOrientationTests/Fixtures/py4dstem-family-real-pins.json` | 3.7 MB | `tools/symmetry/family-real-pins.py` | | +| `DiffractoOrientationTests/Fixtures/slice-4-apps.json` | 12.9 MB | `tools/slice-4/apps-parity/main.swift`, `tools/slice-4/apps-parity/run.sh` | | +| `DiffractoOrientationTests/Fixtures/slice-4-pins.json` | 1.8 MB | `tools/slice-4/pins.py` | | +| `DiffractoOrientationTests/Fixtures/symmetry-pins.json` | 397.2 KB | `tools/cif-symmetry/pins.py`, `tools/orix/ipf-pins.py`, `tools/symmetry/color-table.py` +2 | | +| `DiffractoOrientationTests/Fixtures/trigonal-pins.json` | 14.0 KB | `tools/orix/ipf-pins.py`, `tools/symmetry/trigonal-pins.py` | | +| `DiffractoScatteringTests/Fixtures/slice-2-apps.json` | 2.1 MB | `tools/slice-2/apps-parity/main.swift`, `tools/slice-2/apps-parity/run.sh` | | +| `DiffractoScatteringTests/Fixtures/slice-2-pins.json` | 1.6 MB | `tools/slice-2/pins.py`, `tools/slice-3/index-pins.py`, `tools/slice-4/pins.py` | | diff --git a/tools/build-docs.sh b/tools/build-docs.sh new file mode 100755 index 0000000..dc1a2a7 --- /dev/null +++ b/tools/build-docs.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# Builds the DocC site for every module with a .docc catalog and merges it into one static site. +# tools/build-docs.sh [] e.g. tools/build-docs.sh .docs-site /DiffractoKit +# macOS with Xcode 16 or later. Output is gitignored (.docs-site). +set -euo pipefail +cd "$(dirname "$0")/.." +out="${1:?output dir}" +base="${2:-}" +derived="$(mktemp -d)" +trap 'rm -rf "$derived"' EXIT + +modules=$(find Sources -maxdepth 2 -name '*.docc' -exec basename {} .docc \; | sort) +archives=() +for m in $modules; do + xcodebuild docbuild -scheme "$m" -destination 'generic/platform=macOS' -derivedDataPath "$derived" >"$derived/$m.log" 2>&1 \ + || { tail -30 "$derived/$m.log"; echo "docbuild failed for $m"; exit 1; } + archives+=("$(find "$derived/Build/Products" -name "$m.doccarchive" -maxdepth 3 | head -1)") +done + +merged="$derived/DiffractoKit.doccarchive" +xcrun docc merge "${archives[@]}" --output-path "$merged" +rm -rf "$out" +xcrun docc process-archive transform-for-static-hosting "$merged" --output-path "$out" ${base:+--hosting-base-path "$base"} +# the site root has no page of its own: send it to the merged documentation landing page +printf '' "${base}" > "$out/index.html" +echo "built $out ($(echo "$modules" | wc -l | tr -d ' ') modules)"